├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── Hadapsar-testnet.md ├── LICENSE ├── README.md ├── demo ├── m0_facilitator │ ├── README.md │ ├── bin │ │ ├── create_staker_redeemer.ts │ │ ├── request_redeem_testnet.ts │ │ └── request_stake_testnet.ts │ └── lib │ │ ├── RequestRedeem.ts │ │ └── RequestStake.ts └── m1_facilitator │ ├── .gitignore │ ├── README.md │ ├── bin │ ├── create_depositor_withdrawer.ts │ ├── request_deposit_testnet.ts │ └── request_withdraw_testnet.ts │ └── lib │ ├── Deposit.ts │ ├── Utils.ts │ └── Withdraw.ts ├── facilitator ├── facilitator_m1 ├── fund_facilitator_account ├── index.ts ├── mosaic-1 └── Mosaic-0.1.0.tgz ├── package-lock.json ├── package.json ├── package.sh ├── src ├── common │ ├── Constants.ts │ ├── Exception.ts │ ├── Logger.ts │ ├── ProofGenerator.ts │ ├── TransactionHandler.ts │ ├── TransactionHandlerInterface.ts │ ├── Utils.ts │ ├── handlers │ │ └── ContractEntityHandler.ts │ ├── models │ │ └── ContractEntity.ts │ ├── observer │ │ ├── Comparable.ts │ │ ├── Observer.ts │ │ └── Subject.ts │ ├── repositories │ │ ├── ContractEntityRepository.ts │ │ └── RepositoriesInterface.ts │ └── subscriptions │ │ ├── GraphClient.ts │ │ ├── Subscriber.ts │ │ ├── Subscriptions.ts │ │ └── TransactionFetcher.ts ├── m0_facilitator │ ├── Account.ts │ ├── Config │ │ ├── Config.ts │ │ ├── ConfigFactory.ts │ │ ├── FacilitatorConfig.schema.json │ │ └── GatewayAddresses.ts │ ├── Constants.ts │ ├── Container.ts │ ├── DatabaseFileHelper.ts │ ├── Directory.ts │ ├── Exception.ts │ ├── Facilitator.ts │ ├── GraphQueries │ │ ├── FetchQueries.ts │ │ └── SubscriptionQueries.ts │ ├── SeedData.ts │ ├── Utils.ts │ ├── bin │ │ ├── facilitator-init.ts │ │ ├── facilitator-start.ts │ │ └── facilitator.ts │ ├── handlers │ │ ├── GatewayProvenHandler.ts │ │ ├── Handlers.ts │ │ ├── StateRootAvailableHandler.ts │ │ ├── redeem_and_unstake │ │ │ ├── RedeemIntentConfirmedHandler.ts │ │ │ ├── RedeemIntentDeclaredHandler.ts │ │ │ ├── RedeemProgressedHandler.ts │ │ │ ├── RedeemRequestedHandler.ts │ │ │ └── UnstakeProgressedHandler.ts │ │ └── stake_and_mint │ │ │ ├── MintProgressedHandler.ts │ │ │ ├── StakeIntentConfirmedHandler.ts │ │ │ ├── StakeIntentDeclaredHandler.ts │ │ │ ├── StakeProgressedHandler.ts │ │ │ └── StakeRequestedHandler.ts │ ├── lib │ │ └── FacilitatorInit.ts │ ├── models │ │ ├── AuxiliaryChain.ts │ │ ├── Gateway.ts │ │ ├── Message.ts │ │ └── MessageTransferRequest.ts │ ├── repositories │ │ ├── AuxiliaryChainRepository.ts │ │ ├── GatewayRepository.ts │ │ ├── MessageRepository.ts │ │ ├── MessageTransferRequestRepository.ts │ │ └── Repositories.ts │ ├── services │ │ ├── Services.ts │ │ ├── redeem_and_unstake │ │ │ ├── AcceptRedeemRequestService.ts │ │ │ ├── ConfirmRedeemIntentService.ts │ │ │ ├── ProgressService.ts │ │ │ └── ProveCoGatewayService.ts │ │ └── stake_and_mint │ │ │ ├── AcceptStakeRequestService.ts │ │ │ ├── ConfirmStakeIntentService.ts │ │ │ ├── ProgressService.ts │ │ │ └── ProveGatewayService.ts │ └── types.ts └── m1_facilitator │ ├── Container.ts │ ├── Directory.ts │ ├── Facilitator.ts │ ├── GraphQueries │ ├── FetchQueries.ts │ └── SubscriptionQueries.ts │ ├── SeedDataInitializer.ts │ ├── bin │ ├── facilitator-init.ts │ ├── facilitator-start.ts │ └── facilitator.ts │ ├── commands │ ├── Command.ts │ ├── FacilitatorInit.ts │ └── FacilitatorStart.ts │ ├── handlers │ ├── AvailableStateRootsHandler.ts │ ├── ConfirmDepositIntentsHandler.ts │ ├── ConfirmWithdrawIntentsHandler.ts │ ├── CreatedUtilityTokenHandler.ts │ ├── DeclaredDepositIntentsHandler.ts │ ├── DeclaredWithdrawIntentsHandler.ts │ ├── GatewayProvenHandler.ts │ └── Handlers.ts │ ├── lib │ └── TransactionExecutor.ts │ ├── manifest │ ├── AvatarAccount.ts │ ├── Manifest.ts │ └── manifest.schema.json │ ├── models │ ├── Anchor.ts │ ├── DepositIntent.ts │ ├── ERC20GatewayTokenPair.ts │ ├── Gateway.ts │ ├── Message.ts │ ├── Transaction.ts │ └── WithdrawIntent.ts │ ├── repositories │ ├── AnchorRepository.ts │ ├── DepositIntentRepository.ts │ ├── ERC20GatewayTokenPairRepository.ts │ ├── GatewayRepository.ts │ ├── MessageRepository.ts │ ├── Repositories.ts │ ├── TransactionRepository.ts │ └── WithdrawIntentRepository.ts │ └── services │ ├── ConfirmDepositService.ts │ ├── ConfirmWithdrawService.ts │ ├── ProveGatewayService.ts │ └── Services.ts ├── subgraph ├── abi │ ├── Anchor.json │ ├── ERC20Cogateway.json │ └── ERC20Gateway.json ├── auxiliary │ ├── generated │ │ ├── Anchor │ │ │ └── Anchor.ts │ │ ├── AnchorSchema.ts │ │ ├── ERC20Cogateway │ │ │ └── ERC20Cogateway.ts │ │ └── ERC20CogatewaySchema.ts │ ├── package-lock.json │ ├── package.json │ ├── schema.graphql │ ├── src │ │ ├── AnchorMapping.ts │ │ └── ERC20CogatewayMapping.ts │ └── subgraph.yaml.mustache ├── origin │ ├── generated │ │ ├── Anchor │ │ │ └── Anchor.ts │ │ ├── AnchorSchema.ts │ │ ├── ERC20Gateway │ │ │ └── ERC20Gateway.ts │ │ └── ERC20GatewaySchema.ts │ ├── package-lock.json │ ├── package.json │ ├── schema.graphql │ ├── src │ │ ├── AnchorMapping.ts │ │ └── ERC20GatewayMapping.ts │ └── subgraph.yaml.mustache ├── src │ ├── Constants.ts │ ├── DeployAuxiliarySubgraph.ts │ ├── DeployOriginSubgraph.ts │ └── SubgraphDeployer.ts └── test │ ├── docker-compose.yaml │ └── test.sh ├── system_test ├── README.md ├── common │ ├── AddressHandler.ts │ ├── Faucet.ts │ └── Utils.ts └── m1_facilitator │ ├── DepositSystemTest.ts │ ├── SystemTest.ts │ ├── WithdrawSystemTest.ts │ ├── accounts │ └── account_creation.ts │ └── config.json ├── test ├── common │ ├── ContractEntityRepository │ │ ├── get.test.ts │ │ ├── save.test.ts │ │ └── util.ts │ └── Utils │ │ └── getDefinedOwnProps.test.ts ├── m0_facilitator │ ├── Account │ │ ├── getNonce.test.ts │ │ └── unlock.test.ts │ ├── Config │ │ ├── GatewayAddresses │ │ │ ├── fromGatewayConfig.test.ts │ │ │ └── fromMosaicConfig.test.ts │ │ ├── constructor.test.ts │ │ ├── createWeb3Instance.test.ts │ │ ├── fromChain.test.ts │ │ ├── fromFile.test.ts │ │ ├── getAuxiliaryWeb3.test.ts │ │ └── getOriginWeb3.test.ts │ ├── ConfigFactory │ │ └── getConfig.test.ts │ ├── Database │ │ ├── create.test.ts │ │ └── verify.test.ts │ ├── Facilitator │ │ ├── constructor.test.ts │ │ ├── start.test.ts │ │ └── stop.test.ts │ ├── FacilitatorConfig │ │ ├── fromChain.test.ts │ │ ├── fromFile.test.ts │ │ ├── isFacilitatorConfigPresent.test.ts │ │ ├── remove.test.ts │ │ ├── testdata │ │ │ ├── facilitator-config.json │ │ │ └── invalid-facilitator-config.json │ │ ├── verifySchema.test.ts │ │ └── writeToFacilitatorConfig.test.ts │ ├── SeedData │ │ └── populateDb.test.ts │ ├── TransactionHandler │ │ └── handle.test.ts │ ├── Utils │ │ ├── calculateMessageHash.ts │ │ ├── generateSecret.test.ts │ │ ├── getMessageBoxOffset.test.ts │ │ └── toChecksumAddress.test.ts │ ├── facilitator.sh │ ├── handlers │ │ ├── GatewayProvenHandler │ │ │ └── handle.test.ts │ │ ├── StateRootAvailableHandler │ │ │ └── handle.test.ts │ │ ├── redeem_and_unstake │ │ │ ├── RedeemIntentConfirmedHandler │ │ │ │ └── handle.test.ts │ │ │ ├── RedeemIntentDeclaredHandler │ │ │ │ └── handle.test.ts │ │ │ ├── RedeemProgressedHandler │ │ │ │ └── handle.test.ts │ │ │ ├── RedeemRequestedHandler │ │ │ │ └── handle.test.ts │ │ │ └── UnstakeProgressedHandler │ │ │ │ └── handle.test.ts │ │ └── stake_and_mint │ │ │ ├── MintProgressedHandler │ │ │ └── handle.test.ts │ │ │ ├── StakeIntentConfirmedHandler │ │ │ └── handle.test.ts │ │ │ ├── StakeIntentDeclaredHandler │ │ │ └── handle.test.ts │ │ │ ├── StakeProgressedHandler │ │ │ └── handle.test.ts │ │ │ └── StakeRequestedHandler │ │ │ └── handle.test.ts │ ├── lib │ │ └── FacilitatorInit │ │ │ ├── getFromGatewayConfig.test.ts │ │ │ └── getFromMosaicConfig.test.ts │ ├── models │ │ └── Message │ │ │ └── isValidSecret.test.ts │ ├── observer │ │ ├── NumberUpdate.ts │ │ ├── ObserverSpy.ts │ │ └── Subject │ │ │ ├── attach.test.ts │ │ │ ├── detach.test.ts │ │ │ ├── newUpdate.test.ts │ │ │ ├── notify.test.ts │ │ │ ├── observers.test.ts │ │ │ └── updates.test.ts │ ├── package.sh │ ├── package │ │ └── .gitignore │ ├── repositories │ │ ├── AuxiliaryChainRepository │ │ │ ├── get.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ ├── GatewayRepository │ │ │ ├── get.test.ts │ │ │ ├── getAllByChain.test.ts │ │ │ ├── getByChainGateway.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ ├── MessageRepository │ │ │ ├── get.test.ts │ │ │ ├── getMessagesForConfirmation.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ └── MessageTransferRequestRepository │ │ │ ├── get.test.ts │ │ │ ├── getByMessageHash.test.ts │ │ │ ├── getBySenderProxyNonce.test.ts │ │ │ ├── getWithNullMessageHash.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ ├── services │ │ ├── redeem_and_unstake │ │ │ ├── AcceptRedeemRequest │ │ │ │ └── update.test.ts │ │ │ ├── ConfirmRedeemIntent │ │ │ │ └── update.test.ts │ │ │ ├── ProgressService │ │ │ │ └── update.test.ts │ │ │ └── ProveCoGateway │ │ │ │ └── update.test.ts │ │ └── stake_and_mint │ │ │ ├── AcceptStakeRequestService │ │ │ └── update.test.ts │ │ │ ├── ConfirmStakeIntent │ │ │ └── update.test.ts │ │ │ ├── ProgressService │ │ │ └── update.test.ts │ │ │ └── ProveGateway │ │ │ ├── proveGateway.test.ts │ │ │ └── update.test.ts │ └── subscriptions │ │ ├── GraphClient │ │ ├── constructor.test.ts │ │ └── subscribe.test.ts │ │ ├── Subscriber │ │ ├── subscribe.test.ts │ │ └── unsusbcribe.test.ts │ │ └── TransactionFetcher │ │ ├── constructor.test.ts │ │ └── fetch.test.ts ├── m1_facilitator │ ├── SeedDataInitializer │ │ └── initialize.test.ts │ ├── commands │ │ └── FacilitatorInit │ │ │ └── execute.test.ts │ ├── facilitator │ │ ├── start.test.ts │ │ └── stop.test.ts │ ├── handlers │ │ ├── AvailableStateRootsHandler │ │ │ └── handle.test.ts │ │ ├── ConfirmDepositIntentsHandler │ │ │ └── handle.test.ts │ │ ├── ConfirmWithdrawIntentHandler │ │ │ └── handle.test.ts │ │ ├── CreatedUtilityTokenHandler │ │ │ └── handle.test.ts │ │ ├── DeclaredDepositIntentsHandler │ │ │ └── handle.test.ts │ │ ├── DeclaredWithdrawIntentsHandler │ │ │ └── handle.test.ts │ │ └── GatewayProvenHandler │ │ │ └── handle.test.ts │ ├── isValidSeedData.test.ts │ ├── lib │ │ └── TransactionExecutor │ │ │ ├── add.test.ts │ │ │ └── start.test.ts │ ├── manifest │ │ └── fromFile.test.ts │ ├── models │ │ ├── Anchor │ │ │ ├── compareTo.test.ts │ │ │ ├── constructor.test.ts │ │ │ └── util.ts │ │ └── ERC20GatewayTokenPair │ │ │ ├── compareTo.test.ts │ │ │ ├── constructor.test.ts │ │ │ └── util.ts │ ├── repositories │ │ ├── AnchorRepository │ │ │ ├── get.test.ts │ │ │ └── save.test.ts │ │ ├── DepositIntentRepository │ │ │ ├── get.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ ├── ERC20GatewayTokenPairRepository │ │ │ ├── get.test.ts │ │ │ └── save.test.ts │ │ ├── GatewayRepository │ │ │ ├── get.test.ts │ │ │ ├── getByAnchor.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ ├── MessageRepository │ │ │ ├── get.test.ts │ │ │ ├── getMessageForConfirmation.test.ts │ │ │ ├── getPendingMessagesByGateway.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ ├── TransactionRepository │ │ │ ├── dequeue.test.ts │ │ │ ├── get.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ │ └── WithdrawIntentRepository │ │ │ ├── get.test.ts │ │ │ ├── save.test.ts │ │ │ └── util.ts │ └── services │ │ ├── ConfirmDepositService │ │ └── update.test.ts │ │ ├── ConfirmWithdrawService │ │ └── update.test.ts │ │ └── ProveGateway │ │ └── update.test.ts ├── mocha.test.ts └── test_utils │ ├── SpyAssert.ts │ ├── StubData.ts │ ├── Utils.ts │ └── assert.ts ├── test_integration ├── m0_facilitator │ ├── 01_facilitator_init │ │ ├── 01_init.test.ts │ │ ├── 02_whitelist_workers.test.ts │ │ └── 03_fund_workers.test.ts │ ├── 02_facilitator_start │ │ └── 01_start.test.ts │ ├── 03_stake_and_mint │ │ └── 01_single_staker_single_facilitator.test.ts │ ├── 04_redeem_and_unstake │ │ └── 01_single_redeemer_single_facilitator.test.ts │ ├── 05_facilitator_stop │ │ └── 01_stop.test.ts │ ├── SharedStorage.ts │ ├── Utils.ts │ ├── devchains.sh │ ├── helpers │ │ ├── BaseTokenHelper.ts │ │ ├── EIP20TokenHelper.ts │ │ └── HelperInterface.ts │ ├── kill_facilitator_process.sh │ ├── scripts │ │ ├── base_token │ │ │ ├── deploy_subgraph.sh │ │ │ ├── facilitator_init.sh │ │ │ └── facilitator_start.sh │ │ └── eip20_token │ │ │ ├── deploy_subgraph.sh │ │ │ ├── facilitator_init.sh │ │ │ └── facilitator_start.sh │ └── testdata │ │ ├── BaseToken.json │ │ └── EIP20Token.json └── m1_facilitator │ ├── 00_deployment │ └── deployment.test.ts │ ├── 01_setup │ └── 01_setup.test.ts │ ├── 02_subgraph_deployment │ └── 01_subgraph_deployment.test.ts │ ├── 03_facilitator_init │ ├── 01_facilitator_init.test.ts │ └── FacilitatorManifestGenerator.ts │ ├── 04_facilitator_start │ └── 01_facilitator_start.test.ts │ ├── 05_deposit │ └── 01_deposit.test.ts │ ├── 06_withdraw │ └── 01_withdraw.test.ts │ ├── 07_facilitator_stop │ └── 01_facilitator_stop.test.ts │ ├── docker-compose.yml │ ├── docker.ts │ ├── endpoints.ts │ ├── kill_facilitator_process.sh │ ├── main.sh │ ├── shared.ts │ └── utils.ts ├── testdata ├── m0_facilitator │ ├── 0xae02c7b1c324a8d94a564bc8d713df89eae441fe.json │ └── mosaic.json └── m1_facilitator │ ├── aux_keystore.json │ ├── aux_password │ ├── facilitator_manifest.yml │ ├── origin_keystore.json │ └── origin_password ├── testnet └── m1_facilitator │ └── fund_facilitator │ ├── FundFacilitatorAccount.ts │ └── bin │ └── fund-facilitator-account.ts └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb-base", 4 | "plugin:@typescript-eslint/recommended" 5 | ], 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "project": "./tsconfig.json", 9 | "sourceType": "module", 10 | "ecmaFeatures": { 11 | "modules": true 12 | } 13 | }, 14 | "plugins": [ 15 | "@typescript-eslint", 16 | "json" 17 | ], 18 | "rules": { 19 | "@typescript-eslint/camelcase": "off", 20 | "@typescript-eslint/indent": ["error", 2], 21 | "@typescript-eslint/await-thenable": "error", 22 | "@typescript-eslint/no-for-in-array": "error", 23 | "@typescript-eslint/no-unnecessary-qualifier": "error", 24 | "@typescript-eslint/no-unnecessary-type-assertion": "error", 25 | "@typescript-eslint/no-extraneous-class": [ 26 | "error", 27 | { 28 | "allowStaticOnly": true 29 | } 30 | ], 31 | "@typescript-eslint/prefer-includes": "error", 32 | "@typescript-eslint/restrict-plus-operands": "error", 33 | "@typescript-eslint/no-useless-constructor": "error", 34 | "@typescript-eslint/unified-signatures": "error", 35 | "@typescript-eslint/unbound-method": [ 36 | "error", 37 | { 38 | "ignoreStatic": true 39 | } 40 | ], 41 | "@typescript-eslint/promise-function-async": [ 42 | "error", 43 | { 44 | "checkArrowFunctions": true, 45 | "checkFunctionDeclarations": true, 46 | "checkFunctionExpressions": true, 47 | "checkMethodDeclarations": true 48 | } 49 | ], 50 | "no-console": "off", 51 | "no-underscore-dangle": "off", 52 | "import/no-extraneous-dependencies": "off", 53 | "strict": "off" 54 | }, 55 | "env": { 56 | "mocha": true, 57 | "node": true, 58 | "es6": true 59 | }, 60 | "globals": { 61 | "artifacts": false, 62 | "contract": false, 63 | "assert": false 64 | }, 65 | "settings": { 66 | "import/resolver": { 67 | "node": { 68 | "extensions": [".js", ".jsx", ".ts", ".tsx", ".d.ts"] 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDEs 2 | .idea/ 3 | .vscode/ 4 | *.swp 5 | tags 6 | .DS_Store 7 | # Dependency directories 8 | node_modules/ 9 | 10 | # coverage report 11 | .nyc_output/ 12 | coverage/ 13 | 14 | # Typescript compiler (tsc) generated files. 15 | src/*.js 16 | src/*.js.map 17 | src/**/*.js 18 | src/**/*.js.map 19 | src/**/**/*.js 20 | src/**/**/*.js.map 21 | 22 | # Packaging output 23 | lib/** 24 | openst-facilitator-*.tgz 25 | 26 | # Subgraph build files 27 | subgraph/auxiliary/build/** 28 | subgraph/origin/build/** 29 | subgraph/origin/subgraph.yaml 30 | subgraph/auxiliary/subgraph.yaml 31 | test_integration/m1_facilitator/manifest.yaml 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: node_js 3 | node_js: 4 | - "11" 5 | cache: npm 6 | sudo: required 7 | services: 8 | - docker 9 | env: 10 | global: 11 | - DOCKER_COMPOSE_VERSION=1.23.2 12 | jobs: 13 | - TEST_SUITE="test:unit" 14 | - TEST_SUITE="test:integration:baseToken" 15 | - TEST_SUITE="test:integration:eip20Token" 16 | - TEST_SUITE="test:subgraph" 17 | - TEST_SUITE="test:integration:m1" 18 | before_install: 19 | - sudo rm /usr/local/bin/docker-compose 20 | - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose 21 | - chmod +x docker-compose 22 | - sudo mv docker-compose /usr/local/bin 23 | - sudo apt-get install libsecret-1-dev 24 | branches: 25 | only: 26 | - master 27 | - develop 28 | - /^feature\/.*/ 29 | - /^release-.*/ 30 | - /^hotfix-.*/ 31 | notifications: 32 | email: 33 | recipients: 34 | - ci.report@ost.com 35 | on_success: always 36 | on_failure: always 37 | install: 38 | - npm ci 39 | script: 40 | - npm run ${TEST_SUITE} 41 | after_failure: 42 | - cat /home/travis/.npm/_logs/*-debug.log 43 | -------------------------------------------------------------------------------- /demo/m0_facilitator/bin/create_staker_redeemer.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs'; 3 | 4 | const axios = require('axios'); 5 | const Web3 = require('web3'); 6 | const inquirer = require('inquirer'); 7 | 8 | const FAUCET_URL = 'https://faucet.mosaicdao.org'; 9 | 10 | async function fundFromFaucet(beneficiary: string, chain: string) { 11 | console.log(`Funding ${beneficiary} for chain ${chain}`); 12 | const response = await axios.post( 13 | FAUCET_URL, 14 | { 15 | beneficiary: `${beneficiary}@${chain}`, 16 | }, 17 | ); 18 | console.log(`Transaction hash is ${response.data.txHash}`); 19 | } 20 | 21 | async function createActor() { 22 | const answer = await inquirer.prompt([ 23 | { 24 | type: 'string', 25 | name: 'actor', 26 | message: 'select actor type i.e. staker or redeemer', 27 | validate(input: string) { 28 | return input === 'staker' || input === 'redeemer'; 29 | }, 30 | }, 31 | { 32 | type: 'password', 33 | name: 'password', 34 | message: 'select password for keystore file', 35 | validate(input: string) { 36 | return input.length > 0; 37 | }, 38 | }, 39 | { 40 | type: 'string', 41 | name: 'shouldFund', 42 | message: 'Should fund OST to staker with faucet (y/n)?', 43 | validate(input: string) { 44 | return input === 'y' || input === 'n'; 45 | }, 46 | when: (response: any) => response.actor === 'staker', 47 | }, 48 | ]); 49 | 50 | const web3 = new Web3(); 51 | const stakerAccount = web3.eth.accounts.create(web3.utils.randomHex(8)); 52 | 53 | if (answer.shouldFund === 'y') { 54 | await fundFromFaucet(stakerAccount.address, '5'); 55 | console.log(`✅ Funded ${100} OST to address ${stakerAccount.address}`); 56 | // await fundFromFaucet(stakerAccount.address, '1405'); 57 | } 58 | 59 | const encrypedAccount = stakerAccount.encrypt(answer.password); 60 | 61 | const filePath = path.join(__dirname, '..', '..', '..', `${answer.actor}.json`); 62 | fs.writeFileSync(filePath, JSON.stringify(encrypedAccount, null, ' ')); 63 | console.log(`\n${answer.actor} address ${stakerAccount.address}`); 64 | console.log(`Encrypted key store path: ${filePath}`); 65 | console.log(`\n👉 ${answer.actor} must have fund to perform transactions.`); 66 | console.log(`\n👉 Use public faucet ${'https://goerli-faucet.slock.it/'} for funding on value chain(goerli).\n`); 67 | } 68 | 69 | 70 | createActor().then(() => { 71 | process.exit(0); 72 | }); 73 | -------------------------------------------------------------------------------- /demo/m1_facilitator/.gitignore: -------------------------------------------------------------------------------- 1 | bin/depositor.json 2 | bin/withdrawer.json 3 | -------------------------------------------------------------------------------- /demo/m1_facilitator/lib/Utils.ts: -------------------------------------------------------------------------------- 1 | export default class Utils { 2 | public static ENDPOINT_REGEX = '^(http|https)://(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])(:[0-9]+)?/?(.*)$'; 3 | 4 | public static async sendTransaction( 5 | rawTx: any, 6 | txOptions: { 7 | gas?: string; 8 | gasPrice?: string; 9 | from: string; 10 | }, 11 | ): Promise { 12 | const calculatedTransactionOptions = { 13 | ...txOptions, 14 | gas: (await rawTx.estimateGas({ from: txOptions.from })).toString(), 15 | gasPrice: txOptions.gasPrice ? txOptions.gasPrice : '0x01', 16 | }; 17 | return rawTx.send(calculatedTransactionOptions); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /facilitator: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TS_NODE_FILES=true; TS_NODE_TRANSPILE_ONLY=true; node -r ts-node/register ./src/m0_facilitator/bin/facilitator.ts $@ 4 | -------------------------------------------------------------------------------- /facilitator_m1: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TS_NODE_FILES=true; TS_NODE_TRANSPILE_ONLY=true; node -r ts-node/register ./src/m1_facilitator/bin/facilitator.ts $@ 4 | -------------------------------------------------------------------------------- /fund_facilitator_account: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TS_NODE_FILES=true; TS_NODE_TRANSPILE_ONLY=true; node -r ts-node/register ./testnet/m1_facilitator/fund_facilitator/bin/fund-facilitator-account.ts $@ 4 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /mosaic-1/Mosaic-0.1.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenST/facilitator/3db7bbc452fcecc56b273aa7db84f2b8989d1abc/mosaic-1/Mosaic-0.1.0.tgz -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf ./lib 4 | npm ci 5 | 6 | ./node_modules/.bin/tsc 7 | -------------------------------------------------------------------------------- /src/common/Constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* eslint-disable import/prefer-default-export */ 16 | 17 | /** 18 | * Defines an interval in which the facilitator re-subscribes to the origin 19 | * and auxiliary subgraph nodes. 20 | */ 21 | export const SUBSCRIPTION_RESTART_DURATION = 10 * 60 * 1000; 22 | -------------------------------------------------------------------------------- /src/common/Exception.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* eslint-disable import/prefer-default-export */ 16 | 17 | /** 18 | * This exception is thrown if a handler implementation for the given 19 | * transaction kind was not found while handling transactions in the 20 | * TransactionHandler module. 21 | */ 22 | export class HandlerNotFoundException extends Error { 23 | public constructor(transactionKind: string) { 24 | const message = `Handler implementation for a '${transactionKind}' ` 25 | + 'transaction kind was not found.'; 26 | 27 | super(message); 28 | 29 | Object.setPrototypeOf(this, HandlerNotFoundException.prototype); 30 | this.name = 'HandlerNotFoundException'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/common/Logger.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import winston from 'winston'; 19 | 20 | const { MOSAIC_FACILITATOR_LOG_LEVEL } = process.env; 21 | export default winston.createLogger({ 22 | level: MOSAIC_FACILITATOR_LOG_LEVEL || 'info', 23 | format: winston.format.combine( 24 | winston.format.timestamp(), 25 | winston.format.simple(), 26 | ), 27 | defaultMeta: { service: 'facilitator' }, 28 | transports: [new winston.transports.Console()], 29 | exceptionHandlers: [new winston.transports.Console()], 30 | }); 31 | -------------------------------------------------------------------------------- /src/common/TransactionHandlerInterface.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** Defines an interface for transaction handler classes. */ 16 | export default interface TransactionHandlerInterface { 17 | 18 | /** 19 | * The handle() function accepts transactions of different kinds 20 | * and appropriately handles them. 21 | * 22 | * @throws HandlerNotFoundException if there is no handler mapped to a 23 | * transaction. 24 | */ 25 | handle(bulkTransactions: any): Promise; 26 | }; 27 | -------------------------------------------------------------------------------- /src/common/Utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as Web3Utils from 'web3-utils'; 16 | import BigNumber from 'bignumber.js'; 17 | import Web3 from 'web3'; 18 | 19 | /** 20 | * This class contains general purpose functions. 21 | */ 22 | export default class Utils { 23 | /** 24 | * Returns the checksum address. 25 | * @param address Ethereum Address. 26 | * @returns Checksum address. 27 | */ 28 | public static toChecksumAddress(address: string): string { 29 | return Web3Utils.toChecksumAddress(address); 30 | } 31 | 32 | /** 33 | * Returns object after removing undefined properties. 34 | * @param obj Input object. 35 | */ 36 | public static getDefinedOwnProps(obj: {}): string[] { 37 | const nonUndefinedOwnedProps: string[] = []; 38 | Object.entries(obj).forEach( 39 | ([key, value]): void => { 40 | if (value !== undefined) { 41 | nonUndefinedOwnedProps.push(key); 42 | } 43 | }, 44 | ); 45 | return nonUndefinedOwnedProps; 46 | } 47 | 48 | /** 49 | * Returns the last block timestamp. 50 | */ 51 | public static async latestBlockTimestamp(web3: Web3): Promise { 52 | const block = await web3.eth.getBlock('latest'); 53 | return new BigNumber(block.timestamp); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/common/handlers/ContractEntityHandler.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** An abstract interface to different kinds of transaction handlers. */ 16 | export default abstract class ContractEntityHandler { 17 | /** 18 | * The handle() function receives a homogenous collection of transactions and 19 | * appropriately handle them. 20 | * 21 | * @param transactions A homogenous collection of transactions to handle. 22 | */ 23 | abstract async handle(transactions: any[]): Promise; 24 | } 25 | -------------------------------------------------------------------------------- /src/common/observer/Comparable.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | /** An abstract class that enables less operation. */ 18 | export default abstract class Comparable { 19 | /** 20 | * Compares the current object with the provided one. 21 | * 22 | * @return positive integer, if the current object is greater than the specified object. 23 | * negative integer, if the current object is less than the specified object. 24 | * zero, if the current object is equal to the specified object. 25 | */ 26 | public abstract compareTo(other: Comparable): number; 27 | } 28 | -------------------------------------------------------------------------------- /src/common/observer/Observer.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | /** 18 | * Defines an abstract observer class. 19 | * A class that wants to receive updates from a subject, inherits and 20 | * implements `update()` method. 21 | */ 22 | export default abstract class Observer { 23 | /** 24 | * Notifies the observer about state change in a subject. 25 | * 26 | * @param updates Updates (state change) that happened in a subject. 27 | */ 28 | public abstract async update(updates: T[]): Promise; 29 | } 30 | -------------------------------------------------------------------------------- /src/common/repositories/RepositoriesInterface.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** Defines an abstract interface to repositories container. */ 16 | export default interface RepositoriesInterface { 17 | 18 | /** 19 | * The notify() function notifies all registered listeners of repositories 20 | * within repositories container. 21 | */ 22 | notify(): Promise; 23 | } 24 | -------------------------------------------------------------------------------- /src/m0_facilitator/Constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | export const ORIGIN_GAS_PRICE = '0x2540BE400'; // 10 Gwei 19 | export const AUXILIARY_GAS_PRICE = '0x3B9ACA00'; // 1 Gwei 20 | export const MESSAGE_BOX_OFFSET = '7'; 21 | export const MAX_VALUE = 999999999999999999999999999999999999999999999999999999999999999999999999999999; 22 | -------------------------------------------------------------------------------- /src/m0_facilitator/Container.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | import Subscriptions from '../common/subscriptions/Subscriptions'; 17 | import TransactionHandler from '../common/TransactionHandler'; 18 | 19 | import { Config } from './Config/Config'; 20 | import Facilitator from './Facilitator'; 21 | import fetchQueries from './GraphQueries/FetchQueries'; 22 | import Handlers from './handlers/Handlers'; 23 | import Repositories from './repositories/Repositories'; 24 | import Services from './services/Services'; 25 | import subscriptionQueries from './GraphQueries/SubscriptionQueries'; 26 | 27 | export default class Container { 28 | /** 29 | * This instantiate all the dependencies. 30 | * @param config Config object/ 31 | * @return Promise that resolves to facilitator instance. 32 | */ 33 | public static async create( 34 | config: Config, 35 | 36 | ): Promise { 37 | const repositories = await Repositories.create(config.facilitator.database.path); 38 | const handler = Handlers.create( 39 | repositories, 40 | config.facilitator.auxChainId, 41 | config.gatewayAddresses.eip20GatewayAddress, 42 | config.gatewayAddresses.eip20CoGatewayAddress, 43 | ); 44 | const transactionHandler = new TransactionHandler( 45 | handler, 46 | repositories, 47 | ); 48 | const configOriginChain = config.facilitator.originChain; 49 | const configAuxChainId = config.facilitator.auxChainId; 50 | const subscriptions = await Subscriptions.create( 51 | transactionHandler, 52 | repositories.contractEntityRepository, 53 | fetchQueries, 54 | config.facilitator.chains[configOriginChain].subGraphWs, 55 | config.facilitator.chains[configOriginChain].subGraphRpc, 56 | subscriptionQueries.origin, 57 | config.facilitator.chains[configAuxChainId].subGraphWs, 58 | config.facilitator.chains[configAuxChainId].subGraphRpc, 59 | subscriptionQueries.auxiliary, 60 | ); 61 | 62 | const services = Services.create(repositories, config); 63 | 64 | repositories.attach(services); 65 | 66 | return new Facilitator(subscriptions.originSubscriber, subscriptions.auxiliarySubscriber); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/m0_facilitator/DatabaseFileHelper.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import path from 'path'; 20 | import sqlite from 'sqlite3'; 21 | 22 | import Directory from './Directory'; 23 | import Logger from '../common/Logger'; 24 | 25 | /** 26 | * It creates db file at the path. 27 | */ 28 | export default class DatabaseFileHelper { 29 | private static DBName: string = 'mosaic_facilitator'; 30 | 31 | /** 32 | * It verifies whether the file path is valid. 33 | * @param {string} filePath Database file path. 34 | * @returns {boolean} `true` if file path is valid. 35 | */ 36 | public static verify(filePath: string): boolean { 37 | if ((fs.existsSync(filePath) && (path.extname(filePath) === '.db'))) { 38 | Logger.info('db file verified'); 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | /** 45 | * It creates database and returns the database file path. 46 | * @param originChainId Origin chain id. 47 | * @param auxChainId chain id of the aux chain. 48 | * @param eip20GatewayAddress Gateway address of origin chain. 49 | * @returns Database file path. 50 | */ 51 | public static create( 52 | originChainId: string, 53 | auxChainId: number, 54 | eip20GatewayAddress: string, 55 | ): string { 56 | if (auxChainId === 0) { 57 | throw new Error(`invalid auxiliary chain id ${auxChainId}`); 58 | } 59 | const dbPath: string = Directory.getDBFilePath( 60 | originChainId, 61 | auxChainId, 62 | eip20GatewayAddress, 63 | ); 64 | fs.ensureDirSync(dbPath); 65 | const facilitatorConfigDB = path.join(dbPath, `${`${DatabaseFileHelper.DBName}.db`}`); 66 | new sqlite.Database(facilitatorConfigDB); 67 | return facilitatorConfigDB; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/m0_facilitator/bin/facilitator.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Copyright 2019 OpenST Ltd. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | // ---------------------------------------------------------------------------- 18 | 19 | 20 | import facilitator from 'commander'; 21 | 22 | facilitator 23 | .command('init ', 'initializes the facilitator config') 24 | .command('start ', 'starts the facilitator') 25 | .parse(process.argv); 26 | -------------------------------------------------------------------------------- /src/m0_facilitator/lib/FacilitatorInit.ts: -------------------------------------------------------------------------------- 1 | import MosaicConfig from '@openst/mosaic-chains/lib/src/Config/MosaicConfig'; 2 | import GatewayConfig from '@openst/mosaic-chains/lib/src/Config/GatewayConfig'; 3 | import GatewayAddresses from '../Config/GatewayAddresses'; 4 | 5 | /** 6 | * It contains helper methods for facilitator init command. 7 | */ 8 | export default class FacilitatorInit { 9 | /** 10 | * It provides gateway addresses and origin chain id. It is to be used when mosaic 11 | * config is provided. 12 | * @param auxChainId Auxiliary chain id. 13 | * @param mosaicConfigPath Path to mosaic config. 14 | * @returns originchain id and gatewayaddresses object. 15 | */ 16 | public static getFromMosaicConfig( 17 | auxChainId: number, 18 | mosaicConfigPath: string, 19 | ): { 20 | originChainId?: string; gatewayAddresses?: GatewayAddresses; 21 | } { 22 | const mosaicConfig = MosaicConfig.fromFile(mosaicConfigPath); 23 | const auxChain = mosaicConfig.auxiliaryChains[auxChainId]; 24 | if (!auxChain) { 25 | return {}; 26 | } 27 | 28 | return { 29 | originChainId: mosaicConfig.originChain.chain, 30 | gatewayAddresses: GatewayAddresses.fromMosaicConfig(mosaicConfig, auxChainId), 31 | }; 32 | } 33 | 34 | /** 35 | * It provides gateway addresses and origin chain id. It is to be used when gateway 36 | * config is provided. 37 | * @param auxChainId Auxiliary chain id. 38 | * @param gatewayConfigPath Path to gateway config. 39 | * @returns originchain id and gatewayaddresses object. 40 | */ 41 | public static getFromGatewayConfig( 42 | auxChainId: number, 43 | gatewayConfigPath: string, 44 | ): { 45 | originChainId?: string; gatewayAddresses?: GatewayAddresses; 46 | } { 47 | const gatewayConfig = GatewayConfig.fromFile(gatewayConfigPath); 48 | 49 | if (auxChainId != gatewayConfig.auxChainId) { 50 | return {}; 51 | } 52 | 53 | return { 54 | originChainId: gatewayConfig.mosaicConfig.originChain.chain, 55 | gatewayAddresses: GatewayAddresses.fromGatewayConfig(gatewayConfig), 56 | }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/m0_facilitator/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | export type Bytes32 = string; 19 | export type Address = string; 20 | -------------------------------------------------------------------------------- /src/m1_facilitator/Directory.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import path from 'path'; 16 | import os from 'os'; 17 | 18 | /** 19 | * Provide methods for default mosaic path and facilitator database file path. 20 | */ 21 | export default class Directory { 22 | /** 23 | * Returns mosaic folder path. 24 | */ 25 | public static getMosaicDefaultPath(): string { 26 | return path.join( 27 | os.homedir(), 28 | '.mosaic', 29 | ); 30 | } 31 | 32 | /** 33 | * Returns full path of facilitator database file. 34 | * 35 | * @param architectureLayout Architecture layout. 36 | * @param gatewayAddresses Address of gateway contract. 37 | */ 38 | public static getFacilitatorDatabaseFile( 39 | architectureLayout: string, 40 | gatewayAddresses: string, 41 | ): string { 42 | return path.join( 43 | Directory.getMosaicDefaultPath(), 44 | architectureLayout, 45 | `${gatewayAddresses}.db`, 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/m1_facilitator/bin/facilitator-init.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import commander from 'commander'; 16 | import FacilitatorInit from '../commands/FacilitatorInit'; 17 | import Logger from '../../common/Logger'; 18 | 19 | commander 20 | .option('-m, --manifest ', 'Path to manifest file') 21 | .option('-f, --force', 'Set this option for reinitialize facilitator') 22 | .action(async (options: { 23 | manifest: string; 24 | force?: boolean; 25 | 26 | }): Promise => { 27 | try { 28 | await new FacilitatorInit(options.manifest, options.force ? options.force : false) 29 | .execute(); 30 | } catch (e) { 31 | Logger.error(`facilitator-init::Error in facilitator init command. Reason: ${e.message}`); 32 | } 33 | }).parse(process.argv); 34 | -------------------------------------------------------------------------------- /src/m1_facilitator/bin/facilitator-start.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import commander from 'commander'; 16 | 17 | import Facilitator from '../Facilitator'; 18 | import FacilitatorStart from '../commands/FacilitatorStart'; 19 | import Logger from '../../common/Logger'; 20 | 21 | let facilitator: Facilitator; 22 | 23 | async function terminationHandler(): Promise { 24 | Logger.info('facilitator-start::Stopping facilitator'); 25 | if (facilitator) { 26 | await facilitator.stop(); 27 | } 28 | Logger.info('facilitator-start::Facilitator stopped'); 29 | process.exit(0); 30 | } 31 | 32 | process.on('SIGINT', terminationHandler); 33 | process.on('SIGTERM', terminationHandler); 34 | 35 | commander 36 | .option('-m, --manifest ', 'Path to manifest file.') 37 | .action( 38 | async ( 39 | options: { 40 | manifest: string; 41 | }): Promise => { 42 | try { 43 | await new FacilitatorStart(options.manifest).execute(); 44 | } catch (e) { 45 | Logger.error(`facilitator-start::Error in facilitator start command. Reason: ${e.message}`); 46 | process.exit(1); 47 | } 48 | }, 49 | ).parse(process.argv); 50 | -------------------------------------------------------------------------------- /src/m1_facilitator/bin/facilitator.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import facilitator from 'commander'; 16 | 17 | facilitator.command('init', 'Initializes the facilitator and loads the configuration.') 18 | .command('start', 'Starts the facilitator.') 19 | .parse(process.argv); 20 | -------------------------------------------------------------------------------- /src/m1_facilitator/commands/Command.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** 16 | * Defines interface for each class that implements a command. 17 | */ 18 | export default interface Command { 19 | execute(): Promise; 20 | } 21 | -------------------------------------------------------------------------------- /src/m1_facilitator/commands/FacilitatorStart.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import Command from './Command'; 16 | import Manifest from '../manifest/Manifest'; 17 | import Container from '../Container'; 18 | import SeedDataInitializer from '../SeedDataInitializer'; 19 | 20 | /** 21 | * Implements logic for facilitator start. 22 | */ 23 | export default class FacilitatorStart implements Command { 24 | private manifestPath: string; 25 | 26 | 27 | /** 28 | * Construct FacilitatorStart instance with params. 29 | * 30 | * @param manifestPath Path of manifest file. 31 | */ 32 | public constructor(manifestPath: string) { 33 | this.manifestPath = manifestPath; 34 | } 35 | 36 | /** 37 | * Executes facilitator start command 38 | * - Load manifest file, if file does not exists it will throw an error. 39 | * - Validates seed data. 40 | * - Starts the facilitator. 41 | */ 42 | public async execute(): Promise { 43 | const manifest = Manifest.fromFile(this.manifestPath); 44 | const { 45 | facilitator, 46 | repositories, 47 | } = await Container.create(manifest); 48 | 49 | const seedDataInitializer = new SeedDataInitializer(repositories); 50 | const isSeedDataValid = await seedDataInitializer.isValidSeedData( 51 | manifest.originContractAddresses.erc20_gateway, 52 | ); 53 | if (!isSeedDataValid) { 54 | throw new Error('FacilitatorStart::Seed data validation has failed. Rerun facilitator init with force option.'); 55 | } 56 | 57 | await facilitator.start(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/m1_facilitator/models/DepositIntent.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import BigNumber from 'bignumber.js'; 16 | 17 | import Comparable from '../../common/observer/Comparable'; 18 | 19 | /** 20 | * Represents DepositIntent model object. 21 | */ 22 | export default class DepositIntent extends Comparable { 23 | public messageHash: string; 24 | 25 | public intentHash?: string; 26 | 27 | public tokenAddress?: string; 28 | 29 | public amount?: BigNumber; 30 | 31 | public beneficiary?: string; 32 | 33 | public createdAt?: Date; 34 | 35 | public updatedAt?: Date; 36 | 37 | /** 38 | * Constructor to set fields of DepositIntent model. 39 | * 40 | * @param messageHash Message hash. 41 | * @param [tokenAddress] Value token address. 42 | * @param [amount] Deposited amount. 43 | * @param [beneficiary] Beneficiary address. 44 | * @param [intentHash] Deposit intent hash. 45 | * @param [createdAt] Time at which record is created. 46 | * @param [updatedAt] Time at which record is updated. 47 | */ 48 | public constructor( 49 | messageHash: string, 50 | tokenAddress?: string, 51 | amount?: BigNumber, 52 | beneficiary?: string, 53 | intentHash?: string, 54 | createdAt?: Date, 55 | updatedAt?: Date, 56 | ) { 57 | super(); 58 | this.intentHash = intentHash; 59 | this.messageHash = messageHash; 60 | this.tokenAddress = tokenAddress; 61 | this.amount = amount; 62 | this.beneficiary = beneficiary; 63 | this.createdAt = createdAt; 64 | this.updatedAt = updatedAt; 65 | } 66 | 67 | /** 68 | * Compares two deposit intent models. 69 | * 70 | * @param other A deposit intent object to compare with. 71 | * 72 | * @returns 0 if two objects are equal, 1 if the current object is greater 73 | * and -1 if the specified object is greater. 74 | */ 75 | public compareTo(other: DepositIntent): number { 76 | const currentKey = this.messageHash; 77 | const specifiedKey = other.messageHash; 78 | 79 | if (currentKey > specifiedKey) { 80 | return 1; 81 | } 82 | 83 | if (currentKey < specifiedKey) { 84 | return -1; 85 | } 86 | 87 | return 0; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/m1_facilitator/models/WithdrawIntent.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import BigNumber from 'bignumber.js'; 18 | 19 | import Comparable from '../../common/observer/Comparable'; 20 | 21 | /** 22 | * Represents WithdrawIntent model object. 23 | */ 24 | export default class WithdrawIntent extends Comparable { 25 | public messageHash: string; 26 | 27 | public intentHash?: string; 28 | 29 | public tokenAddress?: string; 30 | 31 | public amount?: BigNumber; 32 | 33 | public beneficiary?: string; 34 | 35 | public createdAt?: Date; 36 | 37 | public updatedAt?: Date; 38 | 39 | /** 40 | * Constructor to set fields of WithdrawIntent model. 41 | * 42 | * @param messageHash Message hash. 43 | * @param [tokenAddress] Utility token address. 44 | * @param [amount] Withdraw amount. 45 | * @param [beneficiary] Beneficiary address. 46 | * *@param [intentHash] Withdraw intent hash. 47 | * @param [createdAt] Time at which record is created. 48 | * @param [updatedAt] Time at which record is updated. 49 | */ 50 | public constructor( 51 | messageHash: string, 52 | tokenAddress?: string, 53 | amount?: BigNumber, 54 | beneficiary?: string, 55 | intentHash?: string, 56 | createdAt?: Date, 57 | updatedAt?: Date, 58 | ) { 59 | super(); 60 | this.messageHash = messageHash; 61 | this.intentHash = intentHash; 62 | this.tokenAddress = tokenAddress; 63 | this.amount = amount; 64 | this.beneficiary = beneficiary; 65 | this.createdAt = createdAt; 66 | this.updatedAt = updatedAt; 67 | } 68 | 69 | /** 70 | * Compares two withdraw intent models. 71 | * 72 | * @param other A withdraw intent object to compare with. 73 | * 74 | * @returns 0 if two objects are equal, 1 if the current object is greater 75 | * and -1 if the specified object is greater. 76 | */ 77 | public compareTo(other: WithdrawIntent): number { 78 | return this.messageHash.localeCompare(other.messageHash); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /subgraph/abi/Anchor.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": false, 7 | "internalType": "uint256", 8 | "name": "_blockNumber", 9 | "type": "uint256" 10 | }, 11 | { 12 | "indexed": false, 13 | "internalType": "bytes32", 14 | "name": "_stateRoot", 15 | "type": "bytes32" 16 | } 17 | ], 18 | "name": "StateRootAvailable", 19 | "type": "event" 20 | }, 21 | { 22 | "constant": true, 23 | "inputs": [], 24 | "name": "consensus", 25 | "outputs": [ 26 | { 27 | "internalType": "contract ConsensusInterface", 28 | "name": "", 29 | "type": "address" 30 | } 31 | ], 32 | "payable": false, 33 | "stateMutability": "view", 34 | "type": "function" 35 | }, 36 | { 37 | "constant": true, 38 | "inputs": [], 39 | "name": "getLatestStateRootBlockNumber", 40 | "outputs": [ 41 | { "internalType": "uint256", "name": "blockNumber_", "type": "uint256" } 42 | ], 43 | "payable": false, 44 | "stateMutability": "view", 45 | "type": "function" 46 | }, 47 | { 48 | "constant": true, 49 | "inputs": [ 50 | { "internalType": "uint256", "name": "_blockNumber", "type": "uint256" } 51 | ], 52 | "name": "getStateRoot", 53 | "outputs": [ 54 | { "internalType": "bytes32", "name": "stateRoot_", "type": "bytes32" } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": false, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "_maxStateRoots", 66 | "type": "uint256" 67 | }, 68 | { 69 | "internalType": "contract ConsensusInterface", 70 | "name": "_consensus", 71 | "type": "address" 72 | } 73 | ], 74 | "name": "setup", 75 | "outputs": [], 76 | "payable": false, 77 | "stateMutability": "nonpayable", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": false, 82 | "inputs": [ 83 | { "internalType": "uint256", "name": "_blockNumber", "type": "uint256" }, 84 | { "internalType": "bytes32", "name": "_stateRoot", "type": "bytes32" } 85 | ], 86 | "name": "anchorStateRoot", 87 | "outputs": [], 88 | "payable": false, 89 | "stateMutability": "nonpayable", 90 | "type": "function" 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /subgraph/auxiliary/generated/AnchorSchema.ts: -------------------------------------------------------------------------------- 1 | // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | 3 | import { 4 | TypedMap, 5 | Entity, 6 | Value, 7 | ValueKind, 8 | store, 9 | Address, 10 | Bytes, 11 | BigInt, 12 | BigDecimal 13 | } from "@graphprotocol/graph-ts"; 14 | 15 | export class AvailableStateRoot extends Entity { 16 | constructor(id: string) { 17 | super(); 18 | this.set("id", Value.fromString(id)); 19 | } 20 | 21 | save(): void { 22 | let id = this.get("id"); 23 | assert(id !== null, "Cannot save AvailableStateRoot entity without an ID"); 24 | assert( 25 | id.kind == ValueKind.STRING, 26 | "Cannot save AvailableStateRoot entity with non-string ID. " + 27 | 'Considering using .toHex() to convert the "id" to a string.' 28 | ); 29 | store.set("AvailableStateRoot", id.toString(), this); 30 | } 31 | 32 | static load(id: string): AvailableStateRoot | null { 33 | return store.get("AvailableStateRoot", id) as AvailableStateRoot | null; 34 | } 35 | 36 | get id(): string { 37 | let value = this.get("id"); 38 | return value.toString(); 39 | } 40 | 41 | set id(value: string) { 42 | this.set("id", Value.fromString(value)); 43 | } 44 | 45 | get anchoredBlockNumber(): BigInt { 46 | let value = this.get("anchoredBlockNumber"); 47 | return value.toBigInt(); 48 | } 49 | 50 | set anchoredBlockNumber(value: BigInt) { 51 | this.set("anchoredBlockNumber", Value.fromBigInt(value)); 52 | } 53 | 54 | get blockNumber(): BigInt { 55 | let value = this.get("blockNumber"); 56 | return value.toBigInt(); 57 | } 58 | 59 | set blockNumber(value: BigInt) { 60 | this.set("blockNumber", Value.fromBigInt(value)); 61 | } 62 | 63 | get blockHash(): Bytes { 64 | let value = this.get("blockHash"); 65 | return value.toBytes(); 66 | } 67 | 68 | set blockHash(value: Bytes) { 69 | this.set("blockHash", Value.fromBytes(value)); 70 | } 71 | 72 | get contractAddress(): Bytes { 73 | let value = this.get("contractAddress"); 74 | return value.toBytes(); 75 | } 76 | 77 | set contractAddress(value: Bytes) { 78 | this.set("contractAddress", Value.fromBytes(value)); 79 | } 80 | 81 | get uts(): BigInt { 82 | let value = this.get("uts"); 83 | return value.toBigInt(); 84 | } 85 | 86 | set uts(value: BigInt) { 87 | this.set("uts", Value.fromBigInt(value)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /subgraph/auxiliary/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mosaic-subgraph", 3 | "license": "UNLICENSED", 4 | "scripts": { 5 | "codegen": "graph codegen", 6 | "build": "graph build", 7 | "deploy": "graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ mosaic/aux-erc20gateway", 8 | "create-local": "graph create --node http://localhost:8020/ mosaic/aux-erc20gateway", 9 | "remove-local": "graph remove --node http://localhost:8020/ mosaic/aux-erc20gateway", 10 | "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 mosaic/aux-erc20gateway" 11 | }, 12 | "dependencies": { 13 | "@graphprotocol/graph-cli": "0.16.1", 14 | "@graphprotocol/graph-ts": "0.16.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /subgraph/auxiliary/schema.graphql: -------------------------------------------------------------------------------- 1 | type AvailableStateRoot @entity { 2 | id: ID! 3 | anchoredBlockNumber: BigInt! # uint256 4 | blockNumber: BigInt! # uint256 5 | blockHash: Bytes! # bytes32 6 | contractAddress: Bytes! # address 7 | uts: BigInt! # uint256 8 | } 9 | 10 | type DeclaredWithdrawIntent @entity { 11 | id: ID! 12 | amount: BigInt! # uint256 13 | nonce: BigInt! # uint256 14 | beneficiary: Bytes! # address 15 | feeGasPrice: BigInt! # uint256 16 | feeGasLimit: BigInt! # uint256 17 | withdrawer: Bytes! # address 18 | utilityToken: Bytes! # address 19 | messageHash: Bytes! # bytes32 20 | blockNumber: BigInt! # uint256 21 | blockHash: Bytes! # bytes32 22 | contractAddress: Bytes! # address 23 | uts: BigInt! # uint256 24 | } 25 | 26 | type ConfirmedDepositIntent @entity { 27 | id: ID! 28 | messageHash: Bytes! # bytes32 29 | blockNumber: BigInt! # uint256 30 | blockHash: Bytes! # bytes32 31 | contractAddress: Bytes! # address 32 | uts: BigInt! # uint256 33 | } 34 | 35 | type ProvenGateway @entity { 36 | id: ID! 37 | remoteGateway: Bytes! # address 38 | provenBlockNumber: BigInt! # uint256 39 | blockNumber: BigInt! # uint256 40 | blockHash: Bytes! # bytes32 41 | contractAddress: Bytes! # address 42 | uts: BigInt! # uint256 43 | } 44 | 45 | type CreatedUtilityToken @entity { 46 | id: ID! 47 | valueToken: Bytes! # address 48 | utilityToken: Bytes! # address 49 | blockNumber: BigInt! # uint256 50 | blockHash: Bytes! # bytes32 51 | contractAddress: Bytes! # address 52 | uts: BigInt! # uint256 53 | } 54 | -------------------------------------------------------------------------------- /subgraph/auxiliary/src/AnchorMapping.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export, prefer-const, prefer-template */ 2 | import { StateRootAvailable } from '../generated/Anchor/Anchor'; 3 | import { AvailableStateRoot } from '../generated/AnchorSchema'; 4 | 5 | export function handleStateRootAvailable(event: StateRootAvailable): void { 6 | let entity = new AvailableStateRoot( 7 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 8 | ); 9 | 10 | entity.anchoredBlockNumber = event.params._blockNumber; 11 | entity.blockNumber = event.block.number; 12 | entity.blockHash = event.block.hash; 13 | entity.contractAddress = event.address; 14 | entity.uts = event.block.timestamp; 15 | 16 | entity.save(); 17 | } 18 | -------------------------------------------------------------------------------- /subgraph/auxiliary/src/ERC20CogatewayMapping.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export, prefer-const, prefer-template */ 2 | import { 3 | DepositIntentConfirmed, 4 | GatewayProven, 5 | UtilityTokenCreated, 6 | WithdrawIntentDeclared, 7 | } from '../generated/ERC20Cogateway/ERC20Cogateway'; 8 | import { 9 | ConfirmedDepositIntent, 10 | ProvenGateway, 11 | CreatedUtilityToken, 12 | DeclaredWithdrawIntent, 13 | } from '../generated/ERC20CogatewaySchema'; 14 | 15 | export function handleDepositIntentConfirmed( 16 | event: DepositIntentConfirmed, 17 | ): void { 18 | let entity = new ConfirmedDepositIntent( 19 | event.transaction.hash.toHex() + '-' + event.logIndex.toString() 20 | ); 21 | entity.messageHash = event.params.messageHash; 22 | entity.blockNumber = event.block.number; 23 | entity.blockHash = event.block.hash; 24 | entity.contractAddress = event.address; 25 | entity.uts = event.block.timestamp; 26 | entity.save(); 27 | } 28 | 29 | export function handleGatewayProven(event: GatewayProven): void { 30 | let entity = new ProvenGateway( 31 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 32 | ); 33 | entity.remoteGateway = event.params.remoteGateway; 34 | entity.provenBlockNumber = event.params.blockNumber; 35 | entity.blockNumber = event.block.number; 36 | entity.blockHash = event.block.hash; 37 | entity.contractAddress = event.address; 38 | entity.uts = event.block.timestamp; 39 | entity.save(); 40 | } 41 | 42 | export function handleUtilityTokenCreated(event: UtilityTokenCreated): void { 43 | let entity = new CreatedUtilityToken( 44 | event.transaction.hash.toHex() + '-' + event.logIndex.toString() 45 | ); 46 | entity.valueToken = event.params.valueToken; 47 | entity.utilityToken = event.params.utilityToken; 48 | entity.blockNumber = event.block.number; 49 | entity.blockHash = event.block.hash; 50 | entity.contractAddress = event.address; 51 | entity.uts = event.block.timestamp; 52 | entity.save(); 53 | } 54 | 55 | export function handleWithdrawIntentDeclared( 56 | event: WithdrawIntentDeclared 57 | ): void { 58 | let entity = new DeclaredWithdrawIntent( 59 | event.transaction.hash.toHex() + '-' + event.logIndex.toString() 60 | ); 61 | entity.amount = event.params.amount; 62 | entity.nonce = event.params.nonce; 63 | entity.beneficiary = event.params.beneficiary; 64 | entity.feeGasPrice = event.params.feeGasPrice; 65 | entity.feeGasLimit = event.params.feeGasLimit; 66 | entity.withdrawer = event.params.withdrawer; 67 | entity.utilityToken = event.params.utilityToken; 68 | entity.messageHash = event.params.messageHash; 69 | entity.blockNumber = event.block.number; 70 | entity.blockHash = event.block.hash; 71 | entity.contractAddress = event.address; 72 | entity.uts = event.block.timestamp; 73 | entity.save(); 74 | } 75 | -------------------------------------------------------------------------------- /subgraph/auxiliary/subgraph.yaml.mustache: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | schema: 3 | file: ./schema.graphql 4 | dataSources: 5 | - kind: ethereum/contract 6 | name: Anchor 7 | network: dev 8 | source: 9 | address: "{{auxiliaryAnchor}}" 10 | abi: Anchor 11 | mapping: 12 | kind: ethereum/events 13 | apiVersion: 0.0.3 14 | language: wasm/assemblyscript 15 | entities: 16 | - AvailableStateRoot 17 | abis: 18 | - name: Anchor 19 | file: ./../abi/Anchor.json 20 | eventHandlers: 21 | - event: StateRootAvailable(uint256,bytes32) 22 | handler: handleStateRootAvailable 23 | file: ./src/AnchorMapping.ts 24 | 25 | - kind: ethereum/contract 26 | name: ERC20Cogateway 27 | network: dev 28 | source: 29 | address: "{{erc20Cogateway}}" 30 | abi: ERC20Cogateway 31 | mapping: 32 | kind: ethereum/events 33 | apiVersion: 0.0.3 34 | language: wasm/assemblyscript 35 | entities: 36 | - ConfirmedDepositIntent 37 | - ProvenGateway 38 | - CreatedUtilityToken 39 | - DeclaredWithdrawIntent 40 | abis: 41 | - name: ERC20Cogateway 42 | file: ../abi/ERC20Cogateway.json 43 | eventHandlers: 44 | - event: DepositIntentConfirmed(bytes32) 45 | handler: handleDepositIntentConfirmed 46 | - event: GatewayProven(address,uint256) 47 | handler: handleGatewayProven 48 | - event: UtilityTokenCreated(address,address) 49 | handler: handleUtilityTokenCreated 50 | - event: WithdrawIntentDeclared(uint256,uint256,address,uint256,uint256,address,address,bytes32) 51 | handler: handleWithdrawIntentDeclared 52 | file: ./src/ERC20CogatewayMapping.ts 53 | -------------------------------------------------------------------------------- /subgraph/origin/generated/AnchorSchema.ts: -------------------------------------------------------------------------------- 1 | // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | 3 | import { 4 | TypedMap, 5 | Entity, 6 | Value, 7 | ValueKind, 8 | store, 9 | Address, 10 | Bytes, 11 | BigInt, 12 | BigDecimal 13 | } from "@graphprotocol/graph-ts"; 14 | 15 | export class AvailableStateRoot extends Entity { 16 | constructor(id: string) { 17 | super(); 18 | this.set("id", Value.fromString(id)); 19 | } 20 | 21 | save(): void { 22 | let id = this.get("id"); 23 | assert(id !== null, "Cannot save AvailableStateRoot entity without an ID"); 24 | assert( 25 | id.kind == ValueKind.STRING, 26 | "Cannot save AvailableStateRoot entity with non-string ID. " + 27 | 'Considering using .toHex() to convert the "id" to a string.' 28 | ); 29 | store.set("AvailableStateRoot", id.toString(), this); 30 | } 31 | 32 | static load(id: string): AvailableStateRoot | null { 33 | return store.get("AvailableStateRoot", id) as AvailableStateRoot | null; 34 | } 35 | 36 | get id(): string { 37 | let value = this.get("id"); 38 | return value.toString(); 39 | } 40 | 41 | set id(value: string) { 42 | this.set("id", Value.fromString(value)); 43 | } 44 | 45 | get anchoredBlockNumber(): BigInt { 46 | let value = this.get("anchoredBlockNumber"); 47 | return value.toBigInt(); 48 | } 49 | 50 | set anchoredBlockNumber(value: BigInt) { 51 | this.set("anchoredBlockNumber", Value.fromBigInt(value)); 52 | } 53 | 54 | get blockNumber(): BigInt { 55 | let value = this.get("blockNumber"); 56 | return value.toBigInt(); 57 | } 58 | 59 | set blockNumber(value: BigInt) { 60 | this.set("blockNumber", Value.fromBigInt(value)); 61 | } 62 | 63 | get blockHash(): Bytes { 64 | let value = this.get("blockHash"); 65 | return value.toBytes(); 66 | } 67 | 68 | set blockHash(value: Bytes) { 69 | this.set("blockHash", Value.fromBytes(value)); 70 | } 71 | 72 | get contractAddress(): Bytes { 73 | let value = this.get("contractAddress"); 74 | return value.toBytes(); 75 | } 76 | 77 | set contractAddress(value: Bytes) { 78 | this.set("contractAddress", Value.fromBytes(value)); 79 | } 80 | 81 | get uts(): BigInt { 82 | let value = this.get("uts"); 83 | return value.toBigInt(); 84 | } 85 | 86 | set uts(value: BigInt) { 87 | this.set("uts", Value.fromBigInt(value)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /subgraph/origin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mosaic-subgraph", 3 | "license": "UNLICENSED", 4 | "scripts": { 5 | "codegen": "graph codegen", 6 | "build": "graph build", 7 | "deploy": "graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ mosaic/origin-erc20gateway", 8 | "create-local": "graph create --node http://localhost:8020/ mosaic/origin-erc20gateway", 9 | "remove-local": "graph remove --node http://localhost:8020/ mosaic/origin-erc20gateway", 10 | "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 mosaic/origin-erc20gateway" 11 | }, 12 | "dependencies": { 13 | "@graphprotocol/graph-cli": "0.16.1", 14 | "@graphprotocol/graph-ts": "0.16.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /subgraph/origin/schema.graphql: -------------------------------------------------------------------------------- 1 | type AvailableStateRoot @entity { 2 | id: ID! 3 | anchoredBlockNumber: BigInt! # uint256 4 | blockNumber: BigInt! # uint256 5 | blockHash: Bytes! # bytes32 6 | contractAddress: Bytes! # address 7 | uts: BigInt! # uint256 8 | } 9 | 10 | type DeclaredDepositIntent @entity { 11 | id: ID! 12 | amount: BigInt! # uint256 13 | nonce: BigInt! # uint256 14 | beneficiary: Bytes! # address 15 | feeGasPrice: BigInt! # uint256 16 | feeGasLimit: BigInt! # uint256 17 | depositor: Bytes! # address 18 | valueToken: Bytes! # address 19 | messageHash: Bytes! # bytes32 20 | blockNumber: BigInt! # uint256 21 | blockHash: Bytes! # bytes32 22 | contractAddress: Bytes! # address 23 | uts: BigInt! # uint256 24 | } 25 | 26 | type ConfirmedWithdrawIntent @entity { 27 | id: ID! 28 | messageHash: Bytes! # bytes32 29 | blockNumber: BigInt! # uint256 30 | blockHash: Bytes! # bytes32 31 | contractAddress: Bytes! # address 32 | uts: BigInt! # uint256 33 | } 34 | 35 | type ProvenGateway @entity { 36 | id: ID! 37 | remoteGateway: Bytes! # address 38 | provenBlockNumber: BigInt! # uint256 39 | blockNumber: BigInt! # uint256 40 | blockHash: Bytes! # bytes32 41 | contractAddress: Bytes! # address 42 | uts: BigInt! # uint256 43 | } 44 | -------------------------------------------------------------------------------- /subgraph/origin/src/AnchorMapping.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export, prefer-const, prefer-template */ 2 | import { StateRootAvailable } from '../generated/Anchor/Anchor'; 3 | import { AvailableStateRoot } from '../generated/AnchorSchema'; 4 | 5 | export function handleStateRootAvailable(event: StateRootAvailable): void { 6 | let entity = new AvailableStateRoot( 7 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 8 | ); 9 | 10 | entity.anchoredBlockNumber = event.params._blockNumber; 11 | entity.blockNumber = event.block.number; 12 | entity.blockHash = event.block.hash; 13 | entity.contractAddress = event.address; 14 | entity.uts = event.block.timestamp; 15 | 16 | entity.save(); 17 | } 18 | -------------------------------------------------------------------------------- /subgraph/origin/src/ERC20GatewayMapping.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const, prefer-template */ 2 | import { 3 | DepositIntentDeclared, 4 | GatewayProven, 5 | WithdrawIntentConfirmed, 6 | } from '../generated/ERC20Gateway/ERC20Gateway'; 7 | import { 8 | DeclaredDepositIntent, 9 | ConfirmedWithdrawIntent, 10 | ProvenGateway, 11 | } from '../generated/ERC20GatewaySchema'; 12 | 13 | export function handleDepositIntentDeclared( 14 | event: DepositIntentDeclared, 15 | ): void { 16 | let entity = new DeclaredDepositIntent( 17 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 18 | ); 19 | 20 | entity.amount = event.params.amount; 21 | entity.nonce = event.params.nonce; 22 | entity.beneficiary = event.params.beneficiary; 23 | entity.feeGasPrice = event.params.feeGasPrice; 24 | entity.feeGasLimit = event.params.feeGasLimit; 25 | entity.depositor = event.params.depositor; 26 | entity.valueToken = event.params.valueToken; 27 | entity.messageHash = event.params.messageHash; 28 | entity.blockNumber = event.block.number; 29 | entity.blockHash = event.block.hash; 30 | entity.contractAddress = event.address; 31 | entity.uts = event.block.timestamp; 32 | 33 | entity.save(); 34 | } 35 | 36 | export function handleGatewayProven( 37 | event: GatewayProven, 38 | ): void { 39 | let entity = new ProvenGateway( 40 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 41 | ); 42 | 43 | entity.provenBlockNumber = event.params.blockNumber; 44 | entity.remoteGateway = event.params.remoteGateway; 45 | entity.blockNumber = event.block.number; 46 | entity.blockHash = event.block.hash; 47 | entity.contractAddress = event.address; 48 | entity.uts = event.block.timestamp; 49 | 50 | entity.save(); 51 | } 52 | 53 | export function handleWithdrawIntentConfirmed( 54 | event: WithdrawIntentConfirmed, 55 | ): void { 56 | let entity = new ConfirmedWithdrawIntent( 57 | event.transaction.hash.toHex() + '_' + event.logIndex.toString(), 58 | ); 59 | 60 | entity.messageHash = event.params.messageHash; 61 | entity.blockNumber = event.block.number; 62 | entity.blockHash = event.block.hash; 63 | entity.contractAddress = event.address; 64 | entity.uts = event.block.timestamp; 65 | 66 | entity.save(); 67 | } 68 | -------------------------------------------------------------------------------- /subgraph/origin/subgraph.yaml.mustache: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | schema: 3 | file: ./schema.graphql 4 | dataSources: 5 | - kind: ethereum/contract 6 | name: Anchor 7 | network: dev 8 | source: 9 | address: "{{originAnchor}}" 10 | abi: Anchor 11 | mapping: 12 | kind: ethereum/events 13 | apiVersion: 0.0.3 14 | language: wasm/assemblyscript 15 | entities: 16 | - AvailableStateRoot 17 | abis: 18 | - name: Anchor 19 | file: ../abi/Anchor.json 20 | eventHandlers: 21 | - event: StateRootAvailable(uint256,bytes32) 22 | handler: handleStateRootAvailable 23 | file: ./src/AnchorMapping.ts 24 | 25 | - kind: ethereum/contract 26 | name: ERC20Gateway 27 | network: dev 28 | source: 29 | address: "{{erc20Gateway}}" 30 | abi: ERC20Gateway 31 | mapping: 32 | kind: ethereum/events 33 | apiVersion: 0.0.3 34 | language: wasm/assemblyscript 35 | entities: 36 | - DeclaredDepositIntent 37 | - ProvenGateway 38 | - ConfirmedWithdrawIntent 39 | abis: 40 | - name: ERC20Gateway 41 | file: ../abi/ERC20Gateway.json 42 | eventHandlers: 43 | - event: DepositIntentDeclared(uint256,uint256,address,uint256,uint256,address,address,bytes32) 44 | handler: handleDepositIntentDeclared 45 | - event: GatewayProven(address,uint256) 46 | handler: handleGatewayProven 47 | - event: WithdrawIntentConfirmed(bytes32) 48 | handler: handleWithdrawIntentConfirmed 49 | file: ./src/ERC20GatewayMapping.ts 50 | 51 | -------------------------------------------------------------------------------- /subgraph/src/Constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** 16 | * Regex to validate graph admin rpc and ipfs endpoint. 17 | */ 18 | export const ENDPOINT_REGEX = '^(http|https)://(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])(:[0-9]+)?/?(.*)$'; 19 | -------------------------------------------------------------------------------- /subgraph/src/DeployOriginSubgraph.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as path from 'path'; 16 | import assert from 'assert'; 17 | 18 | import * as web3Utils from 'web3-utils'; 19 | import SubgraphDeployer from './SubgraphDeployer'; 20 | import Logger from '../../src/common/Logger'; 21 | import {ENDPOINT_REGEX} from "./Constants"; 22 | 23 | const originSubgraphDirectory = path.join(__dirname, '../origin'); 24 | const originSubgraphName = 'mosaic/origin-erc20gateway'; 25 | 26 | /** 27 | * This function parse command line argument and returns the value. 28 | * This function throws error if input validation fails. 29 | */ 30 | function parseArguments(): { 31 | originAnchor: string; 32 | erc20Gateway: string; 33 | graphAdminRPCEndpoint: string; 34 | ipfsEndpoint: string; 35 | } { 36 | assert(process.argv.length === 6); 37 | 38 | const originAnchor = process.argv[2]; 39 | const erc20Gateway = process.argv[3]; 40 | const graphAdminRPCEndpoint = process.argv[4]; 41 | const ipfsEndpoint = process.argv[5]; 42 | 43 | if (!web3Utils.isAddress(originAnchor)) { 44 | throw new Error(`Invalid origin anchor ${originAnchor}`); 45 | } 46 | 47 | if (!web3Utils.isAddress(erc20Gateway)) { 48 | throw new Error(`Invalid gateway address ${erc20Gateway}`); 49 | } 50 | 51 | const regex = new RegExp(ENDPOINT_REGEX); 52 | 53 | if (!regex.test(graphAdminRPCEndpoint)) { 54 | throw new Error(`Invalid graph admin rpc endpoint ${graphAdminRPCEndpoint}`); 55 | } 56 | 57 | if (!regex.test(ipfsEndpoint)) { 58 | throw new Error(`Invalid ipfs endpoint ${ipfsEndpoint}`); 59 | } 60 | 61 | return { 62 | originAnchor, 63 | erc20Gateway, 64 | graphAdminRPCEndpoint, 65 | ipfsEndpoint, 66 | }; 67 | } 68 | 69 | try { 70 | const params = parseArguments(); 71 | 72 | new SubgraphDeployer( 73 | params.graphAdminRPCEndpoint, 74 | params.ipfsEndpoint, 75 | originSubgraphDirectory, 76 | originSubgraphName, 77 | ).deploy({ 78 | originAnchor: params.originAnchor, 79 | erc20Gateway: params.erc20Gateway, 80 | }); 81 | } catch (e) { 82 | Logger.error(`Error in deployment of subgraph ${e.message}`); 83 | process.exit(1); 84 | } 85 | -------------------------------------------------------------------------------- /subgraph/test/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | graph_node: 4 | image: graphprotocol/graph-node:v0.16.0 5 | ports: 6 | - '8000:8000' 7 | - '8001:8001' 8 | - '8020:8020' 9 | depends_on: 10 | - postgres 11 | - ipfs 12 | - geth_node 13 | environment: 14 | postgres_host: postgres:5432 15 | postgres_user: 'postgres' 16 | postgres_pass: 'postgres' 17 | postgres_db: 'mosaic' 18 | ipfs: 'ipfs:5001' 19 | ethereum: '${ethereum}' 20 | RUST_LOG: info 21 | GRAPH_LOG: info 22 | ETHEREUM_POLLING_INTERVAL: 3000 23 | ETHEREUM_REORG_THRESHOLD: 0 24 | geth_node: 25 | image: augurproject/dev-node-geth:v1.9.9 26 | ports: 27 | - "9546:8545" 28 | postgres: 29 | image: postgres:alpine 30 | ports: 31 | - '6432:5432' 32 | environment: 33 | POSTGRES_USER: 'postgres' 34 | POSTGRES_PASSWORD: 'postgres' 35 | POSTGRES_DB: 'mosaic' 36 | ipfs: 37 | image: ipfs/go-ipfs:v0.4.22-rc1 38 | ports: 39 | - '5001:5001' 40 | -------------------------------------------------------------------------------- /subgraph/test/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'` 4 | ethereum=dev:http://${IP}:9546 docker-compose up & 5 | 6 | sleep 30s 7 | 8 | npm run deploy:subgraph:origin 0xda932fc0d5bd5AC06fB2CeCF72Ab05b9CFEE7808 0xda932fc0d5bd5AC06fB2CeCF72Ab05b9CFEE7808 http://localhost:8020 http://localhost:5001 9 | npm run deploy:subgraph:auxiliary 0xda932fc0d5bd5AC06fB2CeCF72Ab05b9CFEE7808 0xda932fc0d5bd5AC06fB2CeCF72Ab05b9CFEE7808 http://localhost:8020 http://localhost:5001 10 | 11 | docker-compose down 12 | 13 | -------------------------------------------------------------------------------- /system_test/README.md: -------------------------------------------------------------------------------- 1 | Steps to run the system test 2 | 3 | To generate ethereum accounts run the account_creation script 4 | 5 | - You should provide account count for the number of accounts to be created and password for each account. 6 | ``` 7 | ./node_modules/.bin/ts-node system_test/m1_facilitator/accounts/account_creation.ts 8 | ``` 9 | 10 | - You should fund these account mannually with GOETH on Goerli chain 11 | 12 | - Add newly created accounts `depositAccounts[]` and `withdrawAccounts[]` in `config.json` file. 13 | 14 | - Now you can run system test with the following command 15 | ``` 16 | npm run test:system_test 17 | ``` 18 | -------------------------------------------------------------------------------- /system_test/m1_facilitator/SystemTest.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import DepositSystemTest from './DepositSystemTest'; 16 | import WithdrawSystemTest from './WithdrawSystemTest'; 17 | import Logger from '../../src/common/Logger'; 18 | 19 | async function runSystemTest(): Promise { 20 | Logger.info('Running deposit and withdraw system test'); 21 | 22 | 23 | await Promise.all([ 24 | DepositSystemTest.run().catch((error): void => { 25 | Logger.info(`error in deposits ${error}`); 26 | }), 27 | WithdrawSystemTest.run().catch((error): void => { 28 | Logger.info(`error in withdraw ${error}`); 29 | }), 30 | ]); 31 | Logger.info('System test completed'); 32 | process.exit(0); 33 | } 34 | 35 | runSystemTest(); 36 | -------------------------------------------------------------------------------- /system_test/m1_facilitator/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "chains": { 3 | "origin": { 4 | "wsEndpoint": "https://rpc.slock.it/goerli", 5 | "graphEndpoint": "", 6 | "valueToken": "0xd426b22f3960d01189a3d548b45a7202489ff4de", 7 | "gateway": "0x9B0fd9FB015d9311738ed5aECfF3A626e7A149C1", 8 | "chainId": 5, 9 | "faucet": "0x743a8310a7482c56fcfc616d3e59013934ba3496" 10 | }, 11 | "auxiliary": { 12 | "wsEndpoint": "wss://chain.mosaicdao.org/hadapsar/wss", 13 | "graphEndpoint": "", 14 | "utilityToken": "0x98266c031529eed13955909050257950e3b0e2e0", 15 | "cogateway": "0x2d986Be491664A5ad13DD5A06820f539d353bb12", 16 | "chainId": 1405, 17 | "faucet": "0x73e4876c03412139751895879c203d1fe0a0e004" 18 | } 19 | }, 20 | "testConfig": { 21 | "deposit": { 22 | "iterations": 2, 23 | "depositorCount": 1, 24 | "concurrencyCount": 2, 25 | "pollingInterval": 1, 26 | "timeoutInterval": 20, 27 | "minAmount": 1500, 28 | "maxAmount": 2500, 29 | "minGasPrice": 5, 30 | "maxGasPrice": 15, 31 | "minGasLimit": 2, 32 | "maxGasLimit": 5 33 | }, 34 | "withdraw": { 35 | "iterations": 2, 36 | "withdrawerCount": 1, 37 | "concurrencyCount": 2, 38 | "pollingInterval": 1, 39 | "timeoutInterval": 20, 40 | "minAmount": 500, 41 | "maxAmount": 700, 42 | "minGasPrice": 5, 43 | "maxGasPrice": 15, 44 | "minGasLimit": 2, 45 | "maxGasLimit": 5 46 | } 47 | }, 48 | "depositAccounts":[], 49 | "withdrawAccounts":[] 50 | } 51 | -------------------------------------------------------------------------------- /test/common/ContractEntityRepository/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import ContractEntity from '../../../src/common/models/ContractEntity'; 19 | import assert from '../../test_utils/assert'; 20 | 21 | /** 22 | * It contains common methods used for testing purpose of ContractEntityRepository. 23 | */ 24 | export default class Util { 25 | /** 26 | * It asserts fields of contract entity repository. 27 | * @param responseContractEntity Contract entity object received as response. 28 | * @param expectedContractEntity Expected contract entity object. 29 | */ 30 | public static assertion( 31 | responseContractEntity: ContractEntity, 32 | expectedContractEntity: ContractEntity, 33 | ): void { 34 | if (expectedContractEntity.timestamp !== undefined) { 35 | assert.isOk( 36 | expectedContractEntity.timestamp.comparedTo( 37 | responseContractEntity.timestamp, 38 | ) === 0, 39 | ); 40 | } 41 | 42 | assert.strictEqual( 43 | expectedContractEntity.entityType, 44 | responseContractEntity.entityType, 45 | 'Expected entity type is different than the one received in response', 46 | ); 47 | 48 | assert.strictEqual( 49 | expectedContractEntity.contractAddress, 50 | responseContractEntity.contractAddress, 51 | 'Expected contract address is different than the one received in response', 52 | ); 53 | 54 | if (expectedContractEntity.createdAt && responseContractEntity.createdAt) { 55 | assert.strictEqual( 56 | expectedContractEntity.createdAt.getTime(), 57 | responseContractEntity.createdAt.getTime(), 58 | 'Expected created at time is different than the one received in response', 59 | ); 60 | } 61 | assert.isNotNull( 62 | responseContractEntity.updatedAt, 63 | 'Updated at should not be null', 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/common/Utils/getDefinedOwnProps.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Utils from '../../../src/common/Utils'; 20 | import assert from '../../test_utils/assert'; 21 | 22 | describe('Utils::getDefinedOwnProps', (): void => { 23 | it('Checks that only defined and owned props are returned.', async (): Promise => { 24 | const obj = { 25 | a: 'A', 26 | b: undefined, 27 | n: 2, 28 | }; 29 | 30 | assert.isOk( 31 | 'toString' in obj, 32 | 'Checks that toString property exists in prototype chain.', 33 | ); 34 | 35 | const props: string[] = Utils.getDefinedOwnProps(obj); 36 | 37 | assert.strictEqual( 38 | props.length, 39 | 2, 40 | 'Only two defined-own properties.', 41 | ); 42 | 43 | assert.notStrictEqual( 44 | props.indexOf('a'), 45 | -1, 46 | 'Property \'a\' is own property and it\'s defined', 47 | ); 48 | 49 | assert.notStrictEqual( 50 | props.indexOf('n'), 51 | -1, 52 | 'Property \'n\' is own property and it\'s defined', 53 | ); 54 | 55 | assert.strictEqual( 56 | props.indexOf('b'), 57 | -1, 58 | 'Property \'b\' is the owned property however undefined one.', 59 | ); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/m0_facilitator/Account/getNonce.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import BigNumber from 'bignumber.js'; 21 | import Account from '../../../src/m0_facilitator/Account'; 22 | import assert from '../../test_utils/assert'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | describe('Account.getNonce', (): void => { 26 | let dummyInitialNonce: BigNumber; 27 | let web3MockObject: any; 28 | 29 | beforeEach((): void => { 30 | dummyInitialNonce = new BigNumber('1'); 31 | web3MockObject = { 32 | eth: { 33 | getTransactionCount: sinon.fake.resolves(dummyInitialNonce), 34 | }, 35 | }; 36 | }); 37 | 38 | afterEach(async (): Promise => { 39 | sinon.restore(); 40 | }); 41 | 42 | it('should return nonce by calling getTransactionCount on web3', async (): Promise => { 43 | const accountObject: Account = new Account( 44 | '0x0000000000000000000000000000000000000001', 45 | ); 46 | const nonce: BigNumber = await accountObject.getNonce(web3MockObject); 47 | assert.deepEqual( 48 | nonce, 49 | dummyInitialNonce, 50 | 'nonce should match', 51 | ); 52 | SpyAssert.assert( 53 | web3MockObject.eth.getTransactionCount, 54 | 1, 55 | [[accountObject.address, 'pending']], 56 | ); 57 | }); 58 | 59 | it('should return incremented nonce from in-memory storage', async (): Promise => { 60 | const accountObject: Account = new Account( 61 | '0x0000000000000000000000000000000000000002', 62 | ); 63 | // call once to have it fetch nonce from web3 64 | await accountObject.getNonce(web3MockObject); 65 | // call second time to fetch incremented nonce from in-memory 66 | const nonce: BigNumber = await accountObject.getNonce(web3MockObject); 67 | assert.deepEqual( 68 | nonce, 69 | dummyInitialNonce.plus(1), 70 | 'nonce should match', 71 | ); 72 | SpyAssert.assert( 73 | web3MockObject.eth.getTransactionCount, 74 | 1, 75 | [[accountObject.address, 'pending']], 76 | ); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/m0_facilitator/Account/unlock.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | import Web3 from 'web3'; 20 | 21 | import Account from '../../../src/m0_facilitator/Account'; 22 | import assert from '../../test_utils/assert'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | describe('Unlock', (): void => { 26 | let web3: Web3; 27 | let validPassword: string; 28 | let accountCreationResponse: Account; 29 | let accountObject: Account; 30 | 31 | beforeEach((): void => { 32 | web3 = new Web3(null); 33 | validPassword = 'validPassword'; 34 | accountCreationResponse = Account.create(web3, validPassword); 35 | accountObject = new Account( 36 | accountCreationResponse.address, 37 | accountCreationResponse.encryptedKeyStore, 38 | ); 39 | }); 40 | 41 | it('should unlock successfully with valid password', (): void => { 42 | const dummyAccount = web3.eth.accounts.create(); 43 | sinon.replace( 44 | web3.eth.accounts, 45 | 'decrypt', 46 | sinon.fake.returns(dummyAccount), 47 | ); 48 | sinon.replace( 49 | web3.eth.accounts.wallet, 50 | 'add', 51 | sinon.fake.returns(dummyAccount), 52 | ); 53 | assert.strictEqual( 54 | accountObject.unlock(web3, validPassword), 55 | true, 56 | 'should return true for successful unlock', 57 | ); 58 | SpyAssert.assert( 59 | web3.eth.accounts.decrypt, 60 | 1, 61 | [[accountObject.encryptedKeyStore, validPassword]], 62 | ); 63 | SpyAssert.assert( 64 | web3.eth.accounts.wallet.add, 65 | 1, 66 | [[dummyAccount]], 67 | ); 68 | }); 69 | 70 | it('should not unlock with invalid password', (): void => { 71 | const inValidPassword = 'inValidPassword'; 72 | 73 | assert.strictEqual( 74 | accountObject.unlock(web3, inValidPassword), 75 | false, 76 | 'should return false for unsuccessful unlock', 77 | ); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /test/m0_facilitator/Config/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import { Config } from '../../../src/m0_facilitator/Config/Config'; 21 | import assert from '../../test_utils/assert'; 22 | import GatewayAddresses from '../../../src/m0_facilitator/Config/GatewayAddresses'; 23 | 24 | describe('Config.constructor()', () => { 25 | it('should pass with valid arguments', () => { 26 | const gatewayAddresses = sinon.createStubInstance(GatewayAddresses); 27 | const facilitator = sinon.fake() as any; 28 | const config = new Config(gatewayAddresses, facilitator); 29 | 30 | assert.strictEqual( 31 | config.facilitator, 32 | facilitator, 33 | 'Facilitator object is different', 34 | ); 35 | assert.strictEqual( 36 | config.gatewayAddresses, 37 | gatewayAddresses, 38 | 'Gateway addresses object is different', 39 | ); 40 | 41 | sinon.restore(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/m0_facilitator/Config/createWeb3Instance.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | import Web3 from 'web3'; 20 | 21 | import Account from '../../../src/m0_facilitator/Account'; 22 | import { 23 | Chain, Config, ConfigType, ENV_WORKER_PASSWORD_PREFIX, 24 | } from '../../../src/m0_facilitator/Config/Config'; 25 | import assert from '../../test_utils/assert'; 26 | import SpyAssert from '../../test_utils/SpyAssert'; 27 | 28 | describe('Config.createWeb3Instance', () => { 29 | let config: Config; let chain: Chain; 30 | 31 | beforeEach(() => { 32 | const mosaicConfigPath = 'testdata/m0_facilitator/mosaic.json'; 33 | const facilitatorConfigPath = 'test/m0_facilitator/FacilitatorConfig/testdata/facilitator-config.json'; 34 | config = Config.fromFile(facilitatorConfigPath, mosaicConfigPath, ConfigType.MOSAIC); 35 | chain = config.facilitator.chains[config.facilitator.originChain]; 36 | }); 37 | 38 | it('should throw when password for worker is not set in ENV variables', () => { 39 | assert.throws( 40 | () => config.createWeb3Instance( 41 | chain, 42 | ), 43 | 'password not found', 44 | ); 45 | }); 46 | 47 | it('should pass when password is available in ENV variables', () => { 48 | const unlockAccountSpy = sinon.replace( 49 | Account.prototype, 50 | 'unlock', 51 | sinon.fake.returns(true), 52 | ); 53 | const envVariableNameForWorkerPassword = `${ENV_WORKER_PASSWORD_PREFIX}${chain.worker}`; 54 | process.env[envVariableNameForWorkerPassword] = '123'; 55 | 56 | const web3 = config.createWeb3Instance(chain); 57 | assert.instanceOf( 58 | web3, 59 | Web3, 60 | 'web3 should be an instance of Web3', 61 | ); 62 | 63 | SpyAssert.assert(unlockAccountSpy, 1, [ 64 | [web3, chain.password], 65 | ]); 66 | 67 | process.env[envVariableNameForWorkerPassword] = undefined; 68 | 69 | sinon.restore(); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /test/m0_facilitator/Config/getAuxiliaryWeb3.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import { assert } from 'chai'; 19 | import sinon from 'sinon'; 20 | import Web3 from 'web3'; 21 | 22 | import { Chain, Config, ConfigType } from '../../../src/m0_facilitator/Config/Config'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | describe('Config.auxiliaryWeb3', () => { 26 | let config: Config; let chain: Chain; 27 | 28 | beforeEach(() => { 29 | const mosaicConfigPath = 'testdata/m0_facilitator/mosaic.json'; 30 | const facilitatorConfigPath = 'test/m0_facilitator/FacilitatorConfig/testdata/facilitator-config.json'; 31 | config = Config.fromFile(facilitatorConfigPath, mosaicConfigPath, ConfigType.MOSAIC); 32 | chain = config.facilitator.chains[config.facilitator.auxChainId]; 33 | }); 34 | 35 | it('should return web3 instance', () => { 36 | const web3 = new Web3(null); 37 | sinon.replace( 38 | config, 39 | 'createWeb3Instance', 40 | sinon.fake.returns(web3), 41 | ); 42 | const { auxiliaryWeb3 } = config; 43 | assert.strictEqual( 44 | auxiliaryWeb3, 45 | web3, 46 | 'should return web3', 47 | ); 48 | SpyAssert.assert( 49 | config.createWeb3Instance, 50 | 1, 51 | [[chain]], 52 | ); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/m0_facilitator/Config/getOriginWeb3.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import { assert } from 'chai'; 19 | import sinon from 'sinon'; 20 | import Web3 from 'web3'; 21 | 22 | import { Chain, Config, ConfigType } from '../../../src/m0_facilitator/Config/Config'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | describe('Config.originWeb3', () => { 26 | let config: Config; let chain: Chain; 27 | 28 | beforeEach(() => { 29 | const mosaicConfigPath = 'testdata/m0_facilitator/mosaic.json'; 30 | const facilitatorConfigPath = 'test/m0_facilitator/FacilitatorConfig/testdata/facilitator-config.json'; 31 | config = Config.fromFile(facilitatorConfigPath, mosaicConfigPath, ConfigType.MOSAIC); 32 | chain = config.facilitator.chains[config.facilitator.originChain]; 33 | }); 34 | 35 | it('should return web3 instance', () => { 36 | const web3 = new Web3(null); 37 | sinon.replace( 38 | config, 39 | 'createWeb3Instance', 40 | sinon.fake.returns(web3), 41 | ); 42 | const { originWeb3 } = config; 43 | assert.strictEqual( 44 | originWeb3, 45 | web3, 46 | 'should return web3', 47 | ); 48 | SpyAssert.assert( 49 | config.createWeb3Instance, 50 | 1, 51 | [[chain]], 52 | ); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/m0_facilitator/Database/create.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import sinon from 'sinon'; 20 | import sqlite from 'sqlite3'; 21 | 22 | import DBFileHelper from '../../../src/m0_facilitator/DatabaseFileHelper'; 23 | import Directory from '../../../src/m0_facilitator/Directory'; 24 | import assert from '../../test_utils/assert'; 25 | import SpyAssert from '../../test_utils/SpyAssert'; 26 | 27 | const auxChainId = 1; 28 | 29 | describe('Database.create()', (): void => { 30 | const originChainId = 'dev'; 31 | const dummyGatewayAddress = '0x34817AF7B685DBD8a360e8Bed3121eb03D56C9BD'; 32 | afterEach(async (): Promise => { 33 | sinon.restore(); 34 | }); 35 | 36 | it('should fail when aux chain id is 0', (): void => { 37 | const auxChainId = 0; 38 | assert.throws( 39 | (): string => DBFileHelper.create(originChainId, auxChainId, dummyGatewayAddress), 40 | `invalid auxiliary chain id ${auxChainId}`, 41 | ); 42 | }); 43 | 44 | it('should pass with valid arguments', (): void => { 45 | const dbPath = 'test/Database/'; 46 | const dbFileName = 'mosaic_facilitator.db'; 47 | 48 | const spyDirectory = sinon.stub( 49 | Directory, 'getDBFilePath', 50 | ).returns(dbPath); 51 | 52 | const sqliteSpy = sinon.stub( 53 | sqlite, 54 | 'Database', 55 | ).returns( 56 | 'sqlite db is created', 57 | ); 58 | 59 | const fsSpy = sinon.stub(fs, 'ensureDirSync').callsFake((): boolean => true); 60 | 61 | const actualFacilitatorConfigPath = DBFileHelper.create(originChainId, auxChainId, dummyGatewayAddress); 62 | const expectedFacilitatorConfigPath = `${dbPath + dbFileName}`; 63 | 64 | SpyAssert.assert(spyDirectory, 1, [[originChainId, auxChainId, dummyGatewayAddress]]); 65 | 66 | SpyAssert.assert(fsSpy, 1, [[dbPath]]); 67 | 68 | SpyAssert.assert(sqliteSpy, 1, [[expectedFacilitatorConfigPath]]); 69 | 70 | assert.strictEqual( 71 | actualFacilitatorConfigPath, 72 | expectedFacilitatorConfigPath, 73 | 'Facilitator config path is incorrect', 74 | ); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /test/m0_facilitator/Database/verify.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import sinon from 'sinon'; 20 | 21 | import DBFileHelper from '../../../src/m0_facilitator/DatabaseFileHelper'; 22 | import assert from '../../test_utils/assert'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | function assertion( 26 | callCount: number, 27 | dbFilePath: string, 28 | expectedStatus: boolean, 29 | message: string, 30 | fsSpy: any, 31 | ): void { 32 | const verificationStatus: boolean = DBFileHelper.verify(dbFilePath); 33 | 34 | SpyAssert.assert(fsSpy, callCount, [[dbFilePath]]); 35 | 36 | assert.strictEqual( 37 | verificationStatus, 38 | expectedStatus, 39 | message, 40 | ); 41 | } 42 | 43 | const dbFilePath = 'tests/Database/OSTFacilitator.db'; 44 | 45 | describe('Database.verify()', (): void => { 46 | afterEach(async (): Promise => { 47 | sinon.restore(); 48 | }); 49 | 50 | it('should pass with valid arguments', (): void => { 51 | const fsSpy = sinon.stub( 52 | fs, 53 | 'existsSync', 54 | ).returns(true); 55 | 56 | assertion(1, dbFilePath, true, 'DB file path is valid.', fsSpy); 57 | }); 58 | 59 | it('should fail when db file path doesn\'t exist', (): void => { 60 | const fsSpy = sinon.stub( 61 | fs, 62 | 'existsSync', 63 | ).returns(false); 64 | 65 | assertion(1, dbFilePath, false, 'Db file path exists.', fsSpy); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /test/m0_facilitator/Facilitator/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import assert from '../../test_utils/assert'; 21 | import Facilitator from '../../../src/m0_facilitator/Facilitator'; 22 | import Subscriber from '../../../src/common/subscriptions/Subscriber'; 23 | 24 | describe('Facilitator.constructor()', () => { 25 | it('should construct with correct parameters', async () => { 26 | const originSubscriber = sinon.createStubInstance(Subscriber); 27 | const auxiliarySubscriber = sinon.createStubInstance(Subscriber); 28 | 29 | const facilitator = new Facilitator( 30 | originSubscriber as any, 31 | auxiliarySubscriber as any, 32 | ); 33 | 34 | assert( 35 | facilitator, 36 | 'Invalid Facilitator object.', 37 | ); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/m0_facilitator/Facilitator/start.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import Facilitator from '../../../src/m0_facilitator/Facilitator'; 21 | import SpyAssert from '../../test_utils/SpyAssert'; 22 | import Subscriber from '../../../src/common/subscriptions/Subscriber'; 23 | 24 | describe('Facilitator.start()', (): void => { 25 | it('should start facilitation', async (): Promise => { 26 | const originSubscriber = sinon.createStubInstance(Subscriber); 27 | const auxiliarySubscriber = sinon.createStubInstance(Subscriber); 28 | 29 | // Overrides infinite loop of setInterval 30 | const clock = sinon.useFakeTimers(); 31 | const facilitator = new Facilitator( 32 | originSubscriber as any, 33 | auxiliarySubscriber as any, 34 | ); 35 | await facilitator.start(); 36 | SpyAssert.assert(originSubscriber.subscribe, 1, [[]]); 37 | SpyAssert.assert(auxiliarySubscriber.subscribe, 1, [[]]); 38 | clock.restore(); 39 | sinon.restore(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/m0_facilitator/Facilitator/stop.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import Facilitator from '../../../src/m0_facilitator/Facilitator'; 21 | import SpyAssert from '../../test_utils/SpyAssert'; 22 | import Subscriber from '../../../src/common/subscriptions/Subscriber'; 23 | 24 | describe('Facilitator.stop()', (): void => { 25 | it('should stop facilitation', async (): Promise => { 26 | const originSubscriber = sinon.createStubInstance(Subscriber); 27 | const auxiliarySubscriber = sinon.createStubInstance(Subscriber); 28 | 29 | const facilitator = new Facilitator( 30 | originSubscriber as any, 31 | auxiliarySubscriber as any, 32 | ); 33 | await facilitator.stop(); 34 | SpyAssert.assert(originSubscriber.unsubscribe, 1, [[]]); 35 | SpyAssert.assert(auxiliarySubscriber.unsubscribe, 1, [[]]); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/m0_facilitator/FacilitatorConfig/fromFile.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import sinon from 'sinon'; 20 | 21 | import { FacilitatorConfig } from '../../../src/m0_facilitator/Config/Config'; 22 | import Utils from '../../../src/m0_facilitator/Utils'; 23 | import assert from '../../test_utils/assert'; 24 | import SpyAssert from '../../test_utils/SpyAssert'; 25 | 26 | describe('FacilitatorConfig.fromFile()', () => { 27 | const facilitatorConfigPath = 'test/Database/facilitator-config.json'; 28 | 29 | function spyFsModule(status: boolean): any { 30 | const fsSpy: any = sinon.stub( 31 | fs, 32 | 'existsSync', 33 | ).callsFake(sinon.fake.returns(status)); 34 | return fsSpy; 35 | } 36 | 37 | function spyUtils(data: any): any { 38 | const fsUtils: any = sinon.stub( 39 | Utils, 40 | 'getJsonDataFromPath', 41 | ).callsFake(sinon.fake.returns(data)); 42 | return fsUtils; 43 | } 44 | 45 | it('should pass with valid arguments', () => { 46 | const originChain = 'dev-origin'; 47 | const fsSpy = spyFsModule(true); 48 | const config = `{"originChain":"${originChain}"}`; 49 | const data = JSON.parse(config); 50 | const fsUtils = spyUtils(data); 51 | 52 | sinon.stub( 53 | FacilitatorConfig, 54 | 'verifySchema', 55 | ); 56 | const fcConfig: FacilitatorConfig = FacilitatorConfig.fromFile(facilitatorConfigPath); 57 | 58 | SpyAssert.assert(fsUtils, 1, [[facilitatorConfigPath]]); 59 | SpyAssert.assert(fsSpy, 1, [[facilitatorConfigPath]]); 60 | assert.strictEqual( 61 | fcConfig.originChain, 62 | originChain, 63 | 'origin chain id is different', 64 | ); 65 | 66 | fsSpy.restore(); 67 | fsUtils.restore(); 68 | sinon.restore(); 69 | }); 70 | 71 | it('should throw exception when file path doesn\'t exists', () => { 72 | const fsSpy = spyFsModule(false); 73 | 74 | assert.throws(() => FacilitatorConfig.fromFile( 75 | facilitatorConfigPath, 76 | ), 77 | 'File path doesn\'t exists'); 78 | 79 | fsSpy.restore(); 80 | sinon.restore(); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /test/m0_facilitator/FacilitatorConfig/remove.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import sinon from 'sinon'; 20 | 21 | import { FacilitatorConfig } from '../../../src/m0_facilitator/Config/Config'; 22 | import Directory from '../../../src/m0_facilitator/Directory'; 23 | import SpyAssert from '../../test_utils/SpyAssert'; 24 | 25 | describe('FacilitatorConfig.remove()', () => { 26 | it('should remove facilitator config from default path', async () => { 27 | const auxChainId = 300; 28 | const originChain = 'dev'; 29 | const dummyGatewayAddress = '0x34817AF7B685DBD8a360e8Bed3121eb03D56C9BD'; 30 | 31 | const removeSyncStub = sinon.stub( 32 | fs, 33 | 'removeSync', 34 | ); 35 | const somePath = 'Some Path'; 36 | const dirStub = sinon.replace( 37 | Directory, 38 | 'getFacilitatorConfigPath', 39 | sinon.fake.returns(somePath), 40 | ); 41 | FacilitatorConfig.remove(originChain, auxChainId, dummyGatewayAddress); 42 | 43 | SpyAssert.assert(dirStub, 1, [[originChain, auxChainId, dummyGatewayAddress]]); 44 | SpyAssert.assert(removeSyncStub, 1, [[somePath]]); 45 | sinon.restore(); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/m0_facilitator/FacilitatorConfig/testdata/facilitator-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "originChain":"dev-origin", 3 | "auxChainId":1000, 4 | "database": { 5 | "path": "/Users/gulshanvasnani/.mosaic/1000/facilitator/OSTFacilitator.db" 6 | }, 7 | "chains": { 8 | "1000": { 9 | "worker": "0x81Df1244dEd6EF44a90a67526E4Ec4497d807F96", 10 | "nodeRpc": "https://localhost.com:8645", 11 | "subGraphWs":"ws://localhost:8000/subgraphs/name/openst/ost-composer", 12 | "subGraphRpc":"http://localhost:8000/subgraphs/name/openst/ost-composer" 13 | }, 14 | "dev-origin": { 15 | "worker": "0xac7E36b3cdDb14Bf1c67dC21fFB24C73d03d8FF7", 16 | "nodeRpc": "https://localhost.com:8545", 17 | "subGraphWs":"ws://localhost:8000/subgraphs/name/openst/ost-composer", 18 | "subGraphRpc":"http://localhost:8000/subgraphs/name/openst/ost-composer" 19 | } 20 | }, 21 | "encryptedAccounts": { 22 | "0xac7E36b3cdDb14Bf1c67dC21fFB24C73d03d8FF7": { 23 | "version": 3, 24 | "id": "b4c08520-2478-495f-a73e-12582c9629aa", 25 | "address": "ac7e36b3cddb14bf1c67dc21ffb24c73d03d8ff7", 26 | "crypto": { 27 | "ciphertext": "246dc793922c46974839ec62325c5f1f19233eacfcd6f5ab840a7cb6b715ccee", 28 | "cipherparams": { 29 | "iv": "144f7dcec03658a3a59695b9d547df26" 30 | }, 31 | "cipher": "aes-128-ctr", 32 | "kdf": "scrypt", 33 | "kdfparams": { 34 | "dklen": 32, 35 | "salt": "0996b6398b2dd5fbabce76ce28437a916abe91b1c99ad342039abd3f9d3ca0ae", 36 | "n": 8192, 37 | "r": 8, 38 | "p": 1 39 | }, 40 | "mac": "15863e0239f101fe60f830115044bd8ae1d15124f0d6f4982dd353cf9d9df13e" 41 | } 42 | }, 43 | "0x81Df1244dEd6EF44a90a67526E4Ec4497d807F96": { 44 | "version": 3, 45 | "id": "992bd18b-7aa7-461e-9e6e-97efc6f6f0df", 46 | "address": "81df1244ded6ef44a90a67526e4ec4497d807f96", 47 | "crypto": { 48 | "ciphertext": "6715634336d9584c8ad56c9f6f1d8f327393a259a2db46e33fe0421a98df6961", 49 | "cipherparams": { 50 | "iv": "f1e0ec89b38fdf2f1c37e776af298372" 51 | }, 52 | "cipher": "aes-128-ctr", 53 | "kdf": "scrypt", 54 | "kdfparams": { 55 | "dklen": 32, 56 | "salt": "de7ec3ce7852e76de6f279713cd7f2252511b99cd3326aa9b1d6d40ead6c3915", 57 | "n": 8192, 58 | "r": 8, 59 | "p": 1 60 | }, 61 | "mac": "900646627149dfcba31bccb2ac05191b695adf6ced7df0a115d001ad2d303940" 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/m0_facilitator/FacilitatorConfig/verifySchema.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import path from 'path'; 20 | 21 | import { FacilitatorConfig } from '../../../src/m0_facilitator/Config/Config'; 22 | import { InvalidFacilitatorConfigException } from '../../../src/m0_facilitator/Exception'; 23 | import assert from '../../test_utils/assert'; 24 | 25 | describe('FacilitatorConfig.verifySchema()', (): void => { 26 | let facilitatorConfig; 27 | let invalidFacilitatorConfig: any; 28 | 29 | it('should pass when facilitator config is valid', async (): Promise => { 30 | facilitatorConfig = JSON.parse( 31 | fs.readFileSync(path.join(__dirname, 'testdata', 'facilitator-config.json')).toString(), 32 | ); 33 | FacilitatorConfig.verifySchema(facilitatorConfig); 34 | }); 35 | 36 | it('should fail when facilitator config is invalid', async (): Promise => { 37 | // In invalid-facilitator-config.json file, key name `database` is changed to db. 38 | 39 | invalidFacilitatorConfig = JSON.parse( 40 | fs.readFileSync( 41 | path.join(__dirname, 'testdata', 'invalid-facilitator-config.json'), 42 | ).toString(), 43 | ); 44 | 45 | assert.throws( 46 | (): void => FacilitatorConfig.verifySchema(invalidFacilitatorConfig), 47 | InvalidFacilitatorConfigException, 48 | ); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/m0_facilitator/FacilitatorConfig/writeToFacilitatorConfig.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import fs from 'fs-extra'; 19 | import path from 'path'; 20 | import sinon from 'sinon'; 21 | 22 | import { FacilitatorConfig } from '../../../src/m0_facilitator/Config/Config'; 23 | import Directory from '../../../src/m0_facilitator/Directory'; 24 | import SpyAssert from '../../test_utils/SpyAssert'; 25 | 26 | const auxiliaryChainId = 1000; 27 | const originChain = 'dev-origin'; 28 | const mosaicDirectoryPath = '.mosaic'; 29 | const dummyGatewayAddress = '0x34817AF7B685DBD8a360e8Bed3121eb03D56C9BD'; 30 | const facilitatorConfigPath = path.join( 31 | mosaicDirectoryPath, 32 | originChain, 33 | auxiliaryChainId.toString(10), 34 | `gateway-${dummyGatewayAddress}`, 35 | Directory.MOSAIC_FACILITATOR_CONFIG, 36 | ); 37 | 38 | describe('FacilitatorConfig.writeToFacilitatorConfig()', (): void => { 39 | afterEach(async (): Promise => { 40 | sinon.restore(); 41 | }); 42 | 43 | it('should pass with valid arguments', (): void => { 44 | sinon.stub( 45 | Directory, 46 | 'getMosaicDirectoryPath', 47 | ).returns(mosaicDirectoryPath); 48 | 49 | sinon.stub( 50 | fs, 51 | 'ensureDirSync', 52 | ); 53 | 54 | const writeFileSyncStub = sinon.stub( 55 | fs, 56 | 'writeFileSync', 57 | ); 58 | 59 | const existsSyncStub = sinon.stub( 60 | fs, 61 | 'existsSync', 62 | ).returns(false); 63 | const fsConfig = FacilitatorConfig.fromChain(originChain, auxiliaryChainId, dummyGatewayAddress); 64 | existsSyncStub.restore(); 65 | 66 | fsConfig.originChain = 'originChain'; 67 | fsConfig.auxChainId = 2; 68 | fsConfig.chains = {}; 69 | fsConfig.encryptedAccounts = {}; 70 | 71 | const fsConfigJson = JSON.stringify(fsConfig, null, ' '); 72 | 73 | fsConfig.writeToFacilitatorConfig(originChain, auxiliaryChainId, dummyGatewayAddress); 74 | 75 | SpyAssert.assert(writeFileSyncStub, 1, [[facilitatorConfigPath, fsConfigJson]]); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/m0_facilitator/Utils/generateSecret.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import * as Web3Utils from 'web3-utils'; 20 | 21 | import * as assert from 'assert'; 22 | import Utils from '../../../src/m0_facilitator/Utils'; 23 | 24 | describe('AcceptRedeemRequestService::generateSecret', (): void => { 25 | it('Checks that secret maches hash lock.', async (): Promise => { 26 | const { 27 | secret, 28 | hashLock, 29 | } = Utils.generateSecret(); 30 | 31 | assert.strictEqual( 32 | Web3Utils.keccak256(secret), 33 | hashLock, 34 | 'The secret matches to the hash lock.', 35 | ); 36 | }); 37 | 38 | it('Checks that generated secret is different.', async (): Promise => { 39 | const { 40 | secret: secret1, 41 | } = Utils.generateSecret(); 42 | 43 | const { 44 | secret: secret2, 45 | } = Utils.generateSecret(); 46 | 47 | const { 48 | secret: secret3, 49 | } = Utils.generateSecret(); 50 | 51 | assert.notStrictEqual( 52 | secret1, 53 | secret2, 54 | 'Generated secrets are different.', 55 | ); 56 | 57 | assert.notStrictEqual( 58 | secret1, 59 | secret3, 60 | 'Generated secrets are different.', 61 | ); 62 | 63 | assert.notStrictEqual( 64 | secret2, 65 | secret3, 66 | 'Generated secrets are different.', 67 | ); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/m0_facilitator/Utils/toChecksumAddress.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import * as sinon from 'sinon'; 19 | import * as utils from 'web3-utils'; 20 | 21 | import assert from '../../test_utils/assert'; 22 | import SpyAssert from '../../test_utils/SpyAssert'; 23 | import Utils from '../../../src/m0_facilitator/Utils'; 24 | 25 | describe('Utils.toChecksumAddress()', () => { 26 | it('should be successfully', () => { 27 | const address = '0x123Ad'; 28 | 29 | const web3Spy = sinon.stub(utils, 'toChecksumAddress').returns(address); 30 | 31 | const actualAddress = Utils.toChecksumAddress(address); 32 | 33 | assert.strictEqual( 34 | actualAddress, 35 | address, 36 | 'Addresses are different', 37 | ); 38 | 39 | SpyAssert.assert(web3Spy, 1, [[address]]); 40 | 41 | sinon.restore(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/m0_facilitator/models/Message/isValidSecret.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import * as web3utils from 'web3-utils'; 19 | 20 | import Message from '../../../../src/m0_facilitator/models/Message'; 21 | import assert from '../../../test_utils/assert'; 22 | import { MessageDirection, MessageType } from '../../../../src/m0_facilitator/repositories/MessageRepository'; 23 | 24 | describe('AuxiliaryChain::get', (): void => { 25 | const message = new Message( 26 | '0x000000000000000000000000000000000000000000000000000001', 27 | MessageType.Stake, 28 | MessageDirection.OriginToAuxiliary, 29 | ); 30 | 31 | message.secret = '1'; 32 | 33 | it('should return true when hashlock is ' 34 | + 'generated from correct secret', async (): Promise => { 35 | assert(message.secret !== undefined); 36 | 37 | const generatedHashLock = web3utils.keccak256(message.secret as string).toString(); 38 | message.hashLock = generatedHashLock; 39 | const result = message.isValidSecret(); 40 | 41 | assert.strictEqual( 42 | result, 43 | true, 44 | 'Hashlock generated from secret should be same', 45 | ); 46 | }); 47 | 48 | it('should return false when for invalid secret', async (): Promise => { 49 | message.hashLock = '12345'; 50 | 51 | const result = message.isValidSecret(); 52 | 53 | assert.strictEqual( 54 | result, 55 | false, 56 | 'Hashlock generated from secret should be different', 57 | ); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/NumberUpdate.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import Comparable from '../../../src/common/observer/Comparable'; 18 | 19 | /** 20 | * The class is intended for testing functionality of observer/subject classes. 21 | * It acts as a subject's update that is passed during notification to observers. 22 | */ 23 | export default class NumberUpdate extends Comparable { 24 | /* Storage */ 25 | 26 | public readonly value: number = 0; 27 | 28 | public compareTo(other: NumberUpdate): number { 29 | return this.value - other.value; 30 | } 31 | 32 | public constructor(value: number) { 33 | super(); 34 | 35 | this.value = value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/ObserverSpy.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import Observer from '../../../src/common/observer/Observer'; 18 | import NumberUpdate from './NumberUpdate'; 19 | 20 | /** 21 | * The class is intended for testing functionality of observer/subject classes. 22 | * 23 | * It's an observer class implementation that spies and collects updates 24 | * to assert later. 25 | */ 26 | export default class ObserverSpy extends Observer { 27 | /* Storage */ 28 | 29 | public wasCalled: boolean = false; 30 | 31 | public spyUpdates: NumberUpdate[] = []; 32 | 33 | 34 | /* Public Functions */ 35 | 36 | public async update(updates: NumberUpdate[]): Promise { 37 | this.wasCalled = true; 38 | this.spyUpdates.push(...updates); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/Subject/attach.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Subject from '../../../../src/common/observer/Subject'; 20 | import assert from '../../../test_utils/assert'; 21 | import NumberUpdate from '../NumberUpdate'; 22 | import ObserverSpy from '../ObserverSpy'; 23 | 24 | interface TestConfigInterface { 25 | subject: Subject; 26 | } 27 | let config: TestConfigInterface; 28 | 29 | describe('Subject::attach', (): void => { 30 | beforeEach(async (): Promise => { 31 | config = { 32 | subject: new Subject(), 33 | }; 34 | }); 35 | 36 | it('Checks newly added observer exists.', async (): Promise => { 37 | const observer1 = new ObserverSpy(); 38 | 39 | config.subject.attach(observer1); 40 | 41 | assert.notStrictEqual( 42 | config.subject.observers.indexOf(observer1), 43 | -1, 44 | 'Newly attached observer does not exist.', 45 | ); 46 | 47 | const observer2 = new ObserverSpy(); 48 | 49 | config.subject.attach(observer2); 50 | 51 | assert.notStrictEqual( 52 | config.subject.observers.indexOf(observer2), 53 | -1, 54 | 'Newly attached observer does not exist.', 55 | ); 56 | }); 57 | 58 | it('Fails if the specified observer is already attached.', async (): Promise => { 59 | const observer = new ObserverSpy(); 60 | 61 | config.subject.attach(observer); 62 | 63 | assert.throws( 64 | (): void => config.subject.attach(observer), 65 | 'The specified observer is already attached.', 66 | ); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/Subject/detach.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Subject from '../../../../src/common/observer/Subject'; 20 | import assert from '../../../test_utils/assert'; 21 | import NumberUpdate from '../NumberUpdate'; 22 | import ObserverSpy from '../ObserverSpy'; 23 | 24 | interface TestConfigInterface { 25 | subject: Subject; 26 | } 27 | let config: TestConfigInterface; 28 | 29 | describe('Subject::detach', (): void => { 30 | beforeEach(async (): Promise => { 31 | config = { 32 | subject: new Subject(), 33 | }; 34 | }); 35 | 36 | it('Checks successful removal of an attached observer.', async (): Promise => { 37 | const observer1 = new ObserverSpy(); 38 | config.subject.attach(observer1); 39 | 40 | const observer2 = new ObserverSpy(); 41 | config.subject.attach(observer2); 42 | 43 | config.subject.detach(observer1); 44 | assert.strictEqual( 45 | config.subject.observers.indexOf(observer1), 46 | -1, 47 | 'Detached observer does not exist.', 48 | ); 49 | 50 | config.subject.detach(observer2); 51 | assert.strictEqual( 52 | config.subject.observers.indexOf(observer2), 53 | -1, 54 | 'Detached observer does not exist.', 55 | ); 56 | }); 57 | 58 | it('Checks silent ignoring of non-attached observer.', async (): Promise => { 59 | const observer1 = new ObserverSpy(); 60 | config.subject.attach(observer1); 61 | 62 | const observer2 = new ObserverSpy(); 63 | 64 | assert.doesNotThrow( 65 | (): void => config.subject.detach(observer2), 66 | ); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/Subject/newUpdate.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Subject from '../../../../src/common/observer/Subject'; 20 | import assert from '../../../test_utils/assert'; 21 | import NumberUpdate from '../NumberUpdate'; 22 | 23 | interface TestConfigInterface { 24 | subject: Subject; 25 | } 26 | let config: TestConfigInterface; 27 | 28 | describe('Subject::newUpdate', (): void => { 29 | beforeEach(async (): Promise => { 30 | config = { 31 | subject: new Subject(), 32 | }; 33 | }); 34 | 35 | it('Checks newly added update exists.', async (): Promise => { 36 | const update1 = new NumberUpdate(1); 37 | 38 | config.subject.newUpdate(update1); 39 | 40 | assert.strictEqual( 41 | config.subject.updates[0], 42 | update1, 43 | 'Newly added update exists.', 44 | ); 45 | 46 | const update2 = new NumberUpdate(2); 47 | 48 | config.subject.newUpdate(update2); 49 | 50 | assert.strictEqual( 51 | config.subject.updates[1], 52 | update2, 53 | 'Newly added update exists.', 54 | ); 55 | }); 56 | 57 | it('Checks de-duplication of updates.', async (): Promise => { 58 | const update1 = new NumberUpdate(1); 59 | config.subject.newUpdate(update1); 60 | 61 | const update2 = new NumberUpdate(2); 62 | config.subject.newUpdate(update2); 63 | 64 | config.subject.newUpdate(update1); 65 | 66 | assert.strictEqual( 67 | config.subject.updates.length, 68 | 2, 69 | 'After de-duplication the updates array contains only two entries.', 70 | ); 71 | 72 | assert.strictEqual( 73 | config.subject.updates[0], 74 | update2, 75 | 'After de-duplication the position 0 consumes update2.', 76 | ); 77 | 78 | assert.strictEqual( 79 | config.subject.updates[1], 80 | update1, 81 | 'After de-duplication, and new addition the position 1 consumes update1.', 82 | ); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/Subject/observers.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Subject from '../../../../src/common/observer/Subject'; 20 | import assert from '../../../test_utils/assert'; 21 | import NumberUpdate from '../NumberUpdate'; 22 | import ObserverSpy from '../ObserverSpy'; 23 | 24 | interface TestConfigInterface { 25 | subject: Subject; 26 | } 27 | let config: TestConfigInterface; 28 | 29 | describe('Subject::observers', (): void => { 30 | beforeEach(async (): Promise => { 31 | config = { 32 | subject: new Subject(), 33 | }; 34 | }); 35 | 36 | it('Checks that initially observers collection is empty.', async (): Promise => { 37 | assert.strictEqual( 38 | config.subject.observers.length, 39 | 0, 40 | 'Registered observers collection is not empty.', 41 | ); 42 | }); 43 | 44 | it('Checks that registered observer is within a collection.', async (): Promise => { 45 | const observer = new ObserverSpy(); 46 | config.subject.attach(observer); 47 | 48 | assert.strictEqual( 49 | config.subject.observers.length, 50 | 1, 51 | 'Registered observers collection length is not 1.', 52 | ); 53 | 54 | assert.strictEqual( 55 | config.subject.observers[0], 56 | observer, 57 | 'Registered observer is not in the subject\'s observers list.', 58 | ); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/m0_facilitator/observer/Subject/updates.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Subject from '../../../../src/common/observer/Subject'; 20 | import assert from '../../../test_utils/assert'; 21 | import NumberUpdate from '../NumberUpdate'; 22 | 23 | interface TestConfigInterface { 24 | subject: Subject; 25 | } 26 | let config: TestConfigInterface; 27 | 28 | 29 | describe('Subject::updates', (): void => { 30 | beforeEach(async (): Promise => { 31 | config = { 32 | subject: new Subject(), 33 | }; 34 | }); 35 | 36 | it('Checks that initially updates collection is empty.', async (): Promise => { 37 | assert.strictEqual( 38 | config.subject.updates.length, 39 | 0, 40 | 'Updates are not empty.', 41 | ); 42 | }); 43 | 44 | it('Checks that registered observer is within a collection.', async (): Promise => { 45 | const update1 = new NumberUpdate(1); 46 | config.subject.newUpdate(update1); 47 | 48 | assert.strictEqual( 49 | config.subject.updates.length, 50 | 1, 51 | 'Updates count is not 1.', 52 | ); 53 | 54 | assert.strictEqual( 55 | config.subject.updates[0], 56 | update1, 57 | 'Newly added update was not found.', 58 | ); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/m0_facilitator/package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | script_dir_path="$(cd "$(dirname "$0")" && pwd)" 4 | root_dir="${script_dir_path}/../.." 5 | test_package_path="${script_dir_path}/package" 6 | 7 | function clean { 8 | cd "${test_package_path}" 9 | 10 | rm -rf "./node_modules" || exit 1 11 | rm -f openst-facilitator-*.tgz || exit 1 12 | rm -f package.json || exit 1 13 | rm -f package-lock.json || exit 1 14 | 15 | cd - 16 | } 17 | 18 | clean 19 | 20 | echo "Switching to root directory." 21 | cd "${root_dir}" || exit 1 22 | 23 | echo "Executing \"npm pack\"." 24 | npm pack || exit 1 25 | 26 | echo "Switching to the package test directory." 27 | cd "${test_package_path}" || exit 1 28 | 29 | echo "Moving npm tarball into the test directory." 30 | mv $root_dir/openst-facilitator-*.tgz . || exit 1 31 | 32 | echo "Initiating npm project for test." 33 | npm init -y || exit 1 34 | npm install assert || exit 1 35 | 36 | echo "Installing openst-facilitator npm package into newly created project." 37 | npm install openst-facilitator-*.tgz || exit 1 38 | 39 | echo "Accessing as binary." 40 | ./node_modules/.bin/facilitator help || exit 1 41 | 42 | echo "Cleaning up generated files." 43 | clean 44 | 45 | echo "Successfully Passed." 46 | -------------------------------------------------------------------------------- /test/m0_facilitator/package/.gitignore: -------------------------------------------------------------------------------- 1 | package.json 2 | package-lock.json 3 | node_modules 4 | openst-facilitator-*.tgz 5 | -------------------------------------------------------------------------------- /test/m0_facilitator/repositories/GatewayRepository/getAllByChain.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import 'mocha'; 18 | 19 | import Repositories from '../../../../src/m0_facilitator/repositories/Repositories'; 20 | import assert from '../../../test_utils/assert'; 21 | import StubData from '../../../test_utils/StubData'; 22 | import Util from './util'; 23 | 24 | interface TestConfigInterface { 25 | repos: Repositories; 26 | } 27 | let config: TestConfigInterface; 28 | 29 | describe('GatewayRepository::getAllByChain', (): void => { 30 | beforeEach(async (): Promise => { 31 | config = { 32 | repos: await Repositories.create(), 33 | }; 34 | }); 35 | 36 | it('should return all gateway by chain', async (): Promise => { 37 | const chainId = '1234'; 38 | const firstGateway = StubData.gatewayRecord(chainId, '0x0000000000000000000000000000000000000002'); 39 | await config.repos.gatewayRepository.save( 40 | firstGateway, 41 | ); 42 | 43 | const secondGateway = StubData.gatewayRecord(chainId, '0x0000000000000000000000000000000000000003'); 44 | await config.repos.gatewayRepository.save( 45 | secondGateway, 46 | ); 47 | 48 | const gateways = await config.repos.gatewayRepository.getAllByChain( 49 | chainId, 50 | ); 51 | 52 | assert.strictEqual( 53 | gateways.length, 54 | 2, 55 | 'It must return expected number of gateways', 56 | ); 57 | 58 | Util.assertGatewayAttributes( 59 | gateways[0], 60 | firstGateway, 61 | ); 62 | Util.assertGatewayAttributes( 63 | gateways[1], 64 | secondGateway, 65 | ); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /test/m0_facilitator/subscriptions/GraphClient/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import assert from '../../../test_utils/assert'; 21 | import GraphClient from '../../../../src/common/subscriptions/GraphClient'; 22 | 23 | describe('GraphClient.constructor()', () => { 24 | let mockApolloClient; 25 | 26 | it('should construct with correct parameters', async () => { 27 | mockApolloClient = sinon.stub as any; 28 | const graphClient = new GraphClient(mockApolloClient); 29 | 30 | assert( 31 | graphClient, 32 | 'Invalid graph client object.', 33 | ); 34 | 35 | sinon.restore(); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/m0_facilitator/subscriptions/TransactionFetcher/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import sinon from 'sinon'; 19 | 20 | import assert from '../../../test_utils/assert'; 21 | import fetchQueries from '../../../../src/m0_facilitator/GraphQueries/FetchQueries'; 22 | import GraphClient from '../../../../src/common/subscriptions/GraphClient'; 23 | import TransactionFetcher from '../../../../src/common/subscriptions/TransactionFetcher'; 24 | 25 | describe('TransactionFetcher.constructor()', (): void => { 26 | it('should construct with correct parameters', async (): Promise => { 27 | const mockApolloClient = sinon.stub as any; 28 | const graphClient = new GraphClient(mockApolloClient); 29 | const transactionFetcher = new TransactionFetcher( 30 | graphClient, sinon.mock() as any, fetchQueries, 31 | ); 32 | 33 | assert( 34 | transactionFetcher, 35 | 'Invalid transaction fetcher object.', 36 | ); 37 | 38 | sinon.restore(); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/m1_facilitator/facilitator/start.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import sinon from 'sinon'; 16 | 17 | import SpyAssert from '../../test_utils/SpyAssert'; 18 | import TransactionExecutor 19 | from '../../../src/m1_facilitator/lib/TransactionExecutor'; 20 | import Subscriber from '../../../src/common/subscriptions/Subscriber'; 21 | import Facilitator from '../../../src/m1_facilitator/Facilitator'; 22 | 23 | describe('Facilitator:start ', () => { 24 | it('should start facilitator', async (): Promise => { 25 | const originTransactionExecutor = sinon.createStubInstance(TransactionExecutor); 26 | 27 | const auxiliaryTransactionExecutor = sinon.createStubInstance(TransactionExecutor); 28 | 29 | const originSubscriber = sinon.createStubInstance(Subscriber); 30 | const auxiliarySubscriber = sinon.createStubInstance(Subscriber); 31 | // Overrides infinite loop of setInterval 32 | const clock = sinon.useFakeTimers(); 33 | 34 | await new Facilitator( 35 | originTransactionExecutor as any, 36 | auxiliaryTransactionExecutor as any, 37 | originSubscriber as any, 38 | auxiliarySubscriber as any, 39 | ).start(); 40 | 41 | SpyAssert.assert( 42 | originTransactionExecutor.start, 43 | 1, 44 | [[]], 45 | ); 46 | SpyAssert.assert( 47 | auxiliaryTransactionExecutor.start, 48 | 1, 49 | [[]], 50 | ); 51 | SpyAssert.assert( 52 | originSubscriber.subscribe, 53 | 1, 54 | [[]], 55 | ); 56 | SpyAssert.assert( 57 | auxiliarySubscriber.subscribe, 58 | 1, 59 | [[]], 60 | ); 61 | 62 | clock.restore(); 63 | sinon.restore(); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/m1_facilitator/facilitator/stop.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import sinon from 'sinon'; 16 | import TransactionExecutor 17 | from '../../../src/m1_facilitator/lib/TransactionExecutor'; 18 | import Subscriber from '../../../src/common/subscriptions/Subscriber'; 19 | import Facilitator from '../../../src/m1_facilitator/Facilitator'; 20 | import SpyAssert from '../../test_utils/SpyAssert'; 21 | 22 | describe('Facilitator:stop ', (): void => { 23 | it('should stop facilitator', async (): Promise => { 24 | const originTransactionExecutor = sinon.createStubInstance(TransactionExecutor); 25 | 26 | const auxiliaryTransactionExecutor = sinon.createStubInstance(TransactionExecutor); 27 | 28 | const originSubscriber = sinon.createStubInstance(Subscriber); 29 | const auxiliarySubscriber = sinon.createStubInstance(Subscriber); 30 | 31 | await new Facilitator( 32 | originTransactionExecutor as any, 33 | auxiliaryTransactionExecutor as any, 34 | originSubscriber as any, 35 | auxiliarySubscriber as any, 36 | ).stop(); 37 | 38 | SpyAssert.assert( 39 | originTransactionExecutor.stop, 40 | 1, 41 | [[]], 42 | ); 43 | SpyAssert.assert( 44 | auxiliaryTransactionExecutor.stop, 45 | 1, 46 | [[]], 47 | ); 48 | SpyAssert.assert( 49 | originSubscriber.unsubscribe, 50 | 1, 51 | [[]], 52 | ); 53 | SpyAssert.assert( 54 | auxiliarySubscriber.unsubscribe, 55 | 1, 56 | [[]], 57 | ); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/m1_facilitator/isValidSeedData.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import BigNumber from 'bignumber.js'; 16 | 17 | import assert from '../test_utils/assert'; 18 | import Gateway, { GatewayType } from '../../src/m1_facilitator/models/Gateway'; 19 | import Repositories from '../../src/m1_facilitator/repositories/Repositories'; 20 | import SeedDataInitializer from '../../src/m1_facilitator/SeedDataInitializer'; 21 | 22 | describe('SeedDataInitializer::isValidSeedData', (): void => { 23 | let config: { 24 | repos: Repositories; 25 | }; 26 | let gatewayAddress: string; 27 | let remoteGatewayAddress: string; 28 | let gatewayType: GatewayType; 29 | let destinationGA: string; 30 | let remoteGatewayLastProvenBlockNumber: BigNumber; 31 | let anchorGA: string; 32 | let createdAt: Date; 33 | let updatedAt: Date; 34 | 35 | beforeEach(async (): Promise => { 36 | config = { 37 | repos: await Repositories.create(), 38 | }; 39 | gatewayAddress = '0x0000000000000000000000000000000000000001'; 40 | remoteGatewayAddress = '0x0000000000000000000000000000000000000002'; 41 | gatewayType = GatewayType.ERC20; 42 | destinationGA = '0x0000000000000000000000000000000000000003'; 43 | remoteGatewayLastProvenBlockNumber = new BigNumber(100); 44 | anchorGA = '0x0000000000000000000000000000000000000004'; 45 | createdAt = new Date(); 46 | updatedAt = new Date(); 47 | }); 48 | 49 | it('Should verify the seed data for given gateway address', async (): Promise => { 50 | const gateway = new Gateway( 51 | Gateway.getGlobalAddress(gatewayAddress), 52 | Gateway.getGlobalAddress(remoteGatewayAddress), 53 | gatewayType, 54 | anchorGA, 55 | remoteGatewayLastProvenBlockNumber, 56 | destinationGA, 57 | createdAt, 58 | updatedAt, 59 | ); 60 | 61 | await config.repos.gatewayRepository.save( 62 | gateway, 63 | ); 64 | 65 | const seedDataInitialiser = new SeedDataInitializer( 66 | config.repos, 67 | ); 68 | 69 | assert.strictEqual( 70 | await seedDataInitialiser.isValidSeedData(gatewayAddress), 71 | true, 72 | `Seed data validation failed for ${gatewayAddress}`, 73 | ); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /test/m1_facilitator/models/Anchor/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'mocha'; 16 | import BigNumber from 'bignumber.js'; 17 | 18 | import { assertAnchorAttributes } from './util'; 19 | import Anchor from '../../../../src/m1_facilitator/models/Anchor'; 20 | 21 | describe('Anchor::constructor', (): void => { 22 | it('checks correct construction of an anchor', async (): Promise => { 23 | const anchorGA = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'; 24 | const lastAnchoredBlockNumber = new BigNumber(1); 25 | const createdAt = new Date(); 26 | const updatedAt = new Date(); 27 | 28 | const anchor = new Anchor( 29 | anchorGA, 30 | lastAnchoredBlockNumber, 31 | createdAt, 32 | updatedAt, 33 | ); 34 | 35 | assertAnchorAttributes( 36 | anchor, 37 | { 38 | anchorGA, 39 | lastAnchoredBlockNumber, 40 | createdAt, 41 | updatedAt, 42 | }, 43 | ); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/m1_facilitator/models/Anchor/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import BigNumber from 'bignumber.js'; 16 | 17 | import Anchor from '../../../../src/m1_facilitator/models/Anchor'; 18 | import assert from '../../../test_utils/assert'; 19 | 20 | export interface AnchorAttributes { 21 | anchorGA?: string; 22 | lastAnchoredBlockNumber?: BigNumber; 23 | createdAt?: Date; 24 | updatedAt?: Date; 25 | } 26 | 27 | export function assertAnchorAttributes( 28 | anchor: Anchor, 29 | attributes: AnchorAttributes, 30 | ): void { 31 | if (Object.prototype.hasOwnProperty.call(attributes, 'anchorGA')) { 32 | assert.strictEqual( 33 | anchor.anchorGA, 34 | attributes.anchorGA, 35 | ); 36 | } 37 | 38 | if (Object.prototype.hasOwnProperty.call(attributes, 'lastAnchoredBlockNumber')) { 39 | assert.isOk( 40 | anchor.lastAnchoredBlockNumber.isEqualTo( 41 | attributes.lastAnchoredBlockNumber as BigNumber, 42 | ), 43 | ); 44 | } 45 | 46 | if (Object.prototype.hasOwnProperty.call(attributes, 'createdAt')) { 47 | assert.strictEqual( 48 | anchor.createdAt, 49 | attributes.createdAt, 50 | ); 51 | } 52 | 53 | if (Object.prototype.hasOwnProperty.call(attributes, 'updatedAt')) { 54 | assert.strictEqual( 55 | anchor.updatedAt, 56 | attributes.updatedAt, 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/m1_facilitator/models/ERC20GatewayTokenPair/constructor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'mocha'; 16 | 17 | import { assertERC20GatewayTokenPairAttributes } from './util'; 18 | import ERC20GatewayTokenPair from '../../../../src/m1_facilitator/models/ERC20GatewayTokenPair'; 19 | import Gateway from '../../../../src/m1_facilitator/models/Gateway'; 20 | 21 | describe('ERC20GatewayTokenPair::constructor', (): void => { 22 | it('checks correct construction of an ERC20GatewayTokenPair', async (): Promise => { 23 | const erc20Gateway = '0xbb9bc244d798123fde783fcc1c72d3bb8c189411'; 24 | const valueToken = '0xbb9bc244d798123fde783fcc1c72d3bb8c189412'; 25 | const utilityToken = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'; 26 | const createdAt = new Date(); 27 | const updatedAt = new Date(); 28 | 29 | const erc20GatewayTokenPair = new ERC20GatewayTokenPair( 30 | Gateway.getGlobalAddress(erc20Gateway), 31 | valueToken, 32 | utilityToken, 33 | createdAt, 34 | updatedAt, 35 | ); 36 | 37 | assertERC20GatewayTokenPairAttributes( 38 | erc20GatewayTokenPair, 39 | { 40 | gatewayGA: Gateway.getGlobalAddress(erc20Gateway), 41 | valueToken, 42 | utilityToken, 43 | createdAt, 44 | updatedAt, 45 | }, 46 | ); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /test/m1_facilitator/models/ERC20GatewayTokenPair/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import ERC20GatewayTokenPair from '../../../../src/m1_facilitator/models/ERC20GatewayTokenPair'; 16 | import assert from '../../../test_utils/assert'; 17 | 18 | export interface ERC20GatewayTokenPairAttributes { 19 | gatewayGA?: string; 20 | valueToken?: string; 21 | utilityToken?: string; 22 | createdAt?: Date; 23 | updatedAt?: Date; 24 | } 25 | 26 | export function assertERC20GatewayTokenPairAttributes( 27 | erc20GatewayTokenPair: ERC20GatewayTokenPair, 28 | attributes: ERC20GatewayTokenPairAttributes, 29 | ): void { 30 | if (Object.prototype.hasOwnProperty.call(attributes, 'gatewayGA')) { 31 | assert.strictEqual( 32 | erc20GatewayTokenPair.gatewayGA, 33 | attributes.gatewayGA, 34 | ); 35 | } 36 | 37 | if (Object.prototype.hasOwnProperty.call(attributes, 'valueToken')) { 38 | assert.strictEqual( 39 | erc20GatewayTokenPair.valueToken, 40 | attributes.valueToken, 41 | ); 42 | } 43 | 44 | if (Object.prototype.hasOwnProperty.call(attributes, 'utilityToken')) { 45 | assert.strictEqual( 46 | erc20GatewayTokenPair.utilityToken, 47 | attributes.utilityToken, 48 | ); 49 | } 50 | 51 | if (Object.prototype.hasOwnProperty.call(attributes, 'createdAt')) { 52 | assert.strictEqual( 53 | erc20GatewayTokenPair.createdAt, 54 | attributes.createdAt, 55 | ); 56 | } 57 | 58 | if (Object.prototype.hasOwnProperty.call(attributes, 'updatedAt')) { 59 | assert.strictEqual( 60 | erc20GatewayTokenPair.updatedAt, 61 | attributes.updatedAt, 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /test/m1_facilitator/repositories/AnchorRepository/get.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'mocha'; 16 | import { InitOptions, Sequelize } from 'sequelize'; 17 | import BigNumber from 'bignumber.js'; 18 | 19 | import { assertAnchorAttributes } from '../../models/Anchor/util'; 20 | import Anchor from '../../../../src/m1_facilitator/models/Anchor'; 21 | import AnchorRepository from '../../../../src/m1_facilitator/repositories/AnchorRepository'; 22 | import assert from '../../../test_utils/assert'; 23 | 24 | interface TestConfiguration { 25 | anchorRepository: AnchorRepository; 26 | } 27 | let config: TestConfiguration; 28 | 29 | describe('AnchorRepository::get', (): void => { 30 | beforeEach(async (): Promise => { 31 | const sequelize = new Sequelize('sqlite::memory:', { logging: false }); 32 | 33 | const initOptions: InitOptions = { 34 | sequelize, 35 | underscored: true, 36 | timestamps: true, 37 | freezeTableName: true, 38 | }; 39 | 40 | config = { 41 | anchorRepository: new AnchorRepository(initOptions), 42 | }; 43 | 44 | await sequelize.sync(); 45 | }); 46 | 47 | it('checks successful retrieval', async (): Promise => { 48 | const anchorGA = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'; 49 | const lastAnchoredBlockNumber = new BigNumber(1); 50 | 51 | const anchor = new Anchor( 52 | anchorGA, 53 | lastAnchoredBlockNumber, 54 | ); 55 | 56 | await config.anchorRepository.save( 57 | anchor, 58 | ); 59 | 60 | const retrievedAnchor: Anchor | null = await config.anchorRepository.get( 61 | anchorGA, 62 | ); 63 | assert(retrievedAnchor !== null); 64 | 65 | assertAnchorAttributes( 66 | retrievedAnchor as Anchor, 67 | { anchorGA, lastAnchoredBlockNumber }, 68 | ); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /test/m1_facilitator/repositories/DepositIntentRepository/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import assert from '../../../test_utils/assert'; 19 | import DepositIntent from '../../../../src/m1_facilitator/models/DepositIntent'; 20 | 21 | const Util = { 22 | 23 | assertDepositIntentAttributes( 24 | inputDepositIntent: DepositIntent, 25 | expectedDepositIntent: DepositIntent, 26 | ): void { 27 | assert.strictEqual( 28 | inputDepositIntent.intentHash, 29 | expectedDepositIntent.intentHash, 30 | 'Mismatch in intent hash.', 31 | ); 32 | 33 | assert.strictEqual( 34 | inputDepositIntent.messageHash, 35 | expectedDepositIntent.messageHash, 36 | 'Mismatch in message hash.', 37 | ); 38 | 39 | assert.strictEqual( 40 | inputDepositIntent.tokenAddress, 41 | expectedDepositIntent.tokenAddress, 42 | 'Mismatch in token address.', 43 | ); 44 | 45 | if (inputDepositIntent.amount && expectedDepositIntent.amount) { 46 | assert.isOk( 47 | inputDepositIntent.amount.eq(expectedDepositIntent.amount), 48 | 'Mismatch in deposit amount.', 49 | ); 50 | } 51 | 52 | 53 | assert.strictEqual( 54 | inputDepositIntent.beneficiary, 55 | expectedDepositIntent.beneficiary, 56 | 'Mismatch in beneficiary address.', 57 | ); 58 | 59 | if (inputDepositIntent.createdAt && expectedDepositIntent.createdAt) { 60 | assert.strictEqual( 61 | inputDepositIntent.createdAt.getTime(), 62 | expectedDepositIntent.createdAt.getTime(), 63 | 'Expected created at time is different than the one received in response.', 64 | ); 65 | } 66 | 67 | assert.isNotNull( 68 | inputDepositIntent.updatedAt, 69 | 'Updated at should not be null', 70 | ); 71 | }, 72 | 73 | }; 74 | 75 | export default Util; 76 | -------------------------------------------------------------------------------- /test/m1_facilitator/repositories/GatewayRepository/getByAnchor.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import BigNumber from 'bignumber.js'; 18 | 19 | import Util from './util'; 20 | import assert from '../../../test_utils/assert'; 21 | import Gateway, { GatewayType } from '../../../../src/m1_facilitator/models/Gateway'; 22 | import Repositories 23 | from '../../../../src/m1_facilitator/repositories/Repositories'; 24 | 25 | describe('Gateway::getByAnchor', (): void => { 26 | let config: { 27 | repos: Repositories; 28 | }; 29 | let gateway: Gateway; 30 | beforeEach(async (): Promise => { 31 | config = { 32 | repos: await Repositories.create(), 33 | }; 34 | gateway = new Gateway( 35 | '0x0000000000000000000000000000000000000001', 36 | '0x0000000000000000000000000000000000000002', 37 | GatewayType.CONSENSUS, 38 | '0x0000000000000000000000000000000000000004', 39 | new BigNumber(100), 40 | '0x0000000000000000000000000000000000000003', 41 | new Date(), 42 | new Date(), 43 | ); 44 | await config.repos.gatewayRepository.save( 45 | gateway, 46 | ); 47 | }); 48 | 49 | it('should pass when fetching Gateway model', async (): Promise => { 50 | const getResponse = await config.repos.gatewayRepository.getByAnchor( 51 | gateway.anchorGA, 52 | ); 53 | 54 | Util.assertGatewayAttributes(getResponse as Gateway, gateway); 55 | }); 56 | 57 | it('should return null when querying for non-existing ' 58 | + 'anchor global address', async (): Promise => { 59 | const nonExistingAnchorGA = '0x0000000000000000000000000000000000000010'; 60 | 61 | const getResponse = await config.repos.gatewayRepository.get( 62 | nonExistingAnchorGA, 63 | ); 64 | 65 | assert.strictEqual( 66 | getResponse, 67 | null, 68 | "Gateway model doesn't exist.", 69 | ); 70 | }); 71 | }) 72 | -------------------------------------------------------------------------------- /test/m1_facilitator/repositories/TransactionRepository/get.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import BigNumber from 'bignumber.js'; 16 | 17 | import Util from './util'; 18 | import Transaction, { TransactionStatus } from '../../../../src/m1_facilitator/models/Transaction'; 19 | import Repositories from '../../../../src/m1_facilitator/repositories/Repositories'; 20 | import assert from '../../../test_utils/assert'; 21 | 22 | describe('TransactionRepository::get', (): void => { 23 | let repos: Repositories; 24 | let fromAddress: string; 25 | let toAddress: string; 26 | let encodedData: string; 27 | let gasPrice: BigNumber; 28 | let gas: BigNumber; 29 | let txHash: string; 30 | let nonce: BigNumber; 31 | let createdAt: Date; 32 | let updatedAt: Date; 33 | 34 | beforeEach(async (): Promise => { 35 | repos = await Repositories.create(); 36 | fromAddress = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'; 37 | toAddress = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413'; 38 | encodedData = 'encodedData'; 39 | gasPrice = new BigNumber(100); 40 | gas = new BigNumber(200); 41 | txHash = 'txHash'; 42 | nonce = new BigNumber(1); 43 | createdAt = new Date(); 44 | updatedAt = new Date(); 45 | }); 46 | 47 | it('should fetch record from transaction repository.', async (): Promise => { 48 | const expectedTransaction = new Transaction( 49 | fromAddress, 50 | toAddress, 51 | encodedData, 52 | gasPrice, 53 | TransactionStatus.Pending, 54 | gas, 55 | undefined, 56 | txHash, 57 | nonce, 58 | createdAt, 59 | updatedAt, 60 | ); 61 | const createdTransaction = await repos.originTransactionRepository.save(expectedTransaction); 62 | const actualTransaction = await repos.originTransactionRepository.get( 63 | createdTransaction.id as BigNumber, 64 | ); 65 | assert(actualTransaction !== null); 66 | Util.assertTransactionAttributes(actualTransaction as Transaction, expectedTransaction); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/m1_facilitator/repositories/WithdrawIntentRepository/util.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import assert from '../../../test_utils/assert'; 19 | import WithdrawIntent from '../../../../src/m1_facilitator/models/WithdrawIntent'; 20 | 21 | const Util = { 22 | assertWithdrawIntentAttributes( 23 | inputWithdrawIntent: WithdrawIntent, 24 | expectedWithdrawIntent: WithdrawIntent, 25 | ): void { 26 | assert.strictEqual( 27 | inputWithdrawIntent.intentHash, 28 | expectedWithdrawIntent.intentHash, 29 | 'Mismatch in intent hash.', 30 | ); 31 | 32 | assert.strictEqual( 33 | inputWithdrawIntent.messageHash, 34 | expectedWithdrawIntent.messageHash, 35 | 'Mismatch in message hash.', 36 | ); 37 | 38 | assert.strictEqual( 39 | inputWithdrawIntent.tokenAddress, 40 | expectedWithdrawIntent.tokenAddress, 41 | 'Mismatch in token address.', 42 | ); 43 | 44 | assert.isOk( 45 | inputWithdrawIntent.amount 46 | && expectedWithdrawIntent.amount 47 | && inputWithdrawIntent.amount.eq(expectedWithdrawIntent.amount), 48 | 'Expected Withdraw amount is ' 49 | + `${inputWithdrawIntent.amount && inputWithdrawIntent.amount.toString(10)} but got` 50 | + `${expectedWithdrawIntent.amount && expectedWithdrawIntent.amount.toString(10)}.`, 51 | ); 52 | 53 | assert.strictEqual( 54 | inputWithdrawIntent.beneficiary, 55 | expectedWithdrawIntent.beneficiary, 56 | 'Mismatch in beneficiary address.', 57 | ); 58 | 59 | assert.strictEqual( 60 | inputWithdrawIntent.createdAt && inputWithdrawIntent.createdAt.getTime(), 61 | expectedWithdrawIntent.createdAt && expectedWithdrawIntent.createdAt.getTime(), 62 | 'Expected created at time is different than the one received in response.', 63 | ); 64 | 65 | assert.isNotNull( 66 | inputWithdrawIntent.updatedAt, 67 | 'Updated at should not be null', 68 | ); 69 | }, 70 | 71 | }; 72 | 73 | export default Util; 74 | -------------------------------------------------------------------------------- /test/mocha.test.ts: -------------------------------------------------------------------------------- 1 | import Logger from '../src/common/Logger'; 2 | 3 | let loggerMode: boolean; 4 | 5 | before( 6 | (): void => { 7 | loggerMode = Logger.silent; 8 | Logger.silent = true; 9 | }, 10 | ); 11 | 12 | 13 | after( 14 | (): void => { 15 | Logger.silent = loggerMode; 16 | }, 17 | ); 18 | -------------------------------------------------------------------------------- /test/test_utils/SpyAssert.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import assert from './assert'; 19 | 20 | /** 21 | * This class includes the utility functions to assert spy data. 22 | */ 23 | export default class SpyAssert { 24 | /** 25 | * @function assertSpy 26 | * 27 | * Asserts the spy data. 28 | * 29 | * @param {Object} spy Spy object. 30 | * @param {number} callCount of times the spy was called. 31 | * @param {Array} inputArgs Input arguments 32 | * 33 | */ 34 | public static assert(spy: any, callCount: number, inputArgs: any[]): void { 35 | assert.strictEqual( 36 | spy.callCount, 37 | callCount, 38 | 'Call count must match with the expected value.', 39 | ); 40 | if (inputArgs) { 41 | for (let i = 0; i < callCount; i += 1) { 42 | const expectedArguments = inputArgs[i]; 43 | const actualArguments = spy.args[i]; 44 | assert.strictEqual( 45 | actualArguments.length, 46 | expectedArguments.length, 47 | 'Expected and actual argument counts should be same', 48 | ); 49 | for (let params = 0; params < actualArguments.length; params += 1) { 50 | assert.deepStrictEqual( 51 | actualArguments[params], 52 | expectedArguments[params], 53 | `Input param value ${ 54 | actualArguments[params] 55 | } must match with the expected param value ${ 56 | expectedArguments[params] 57 | }.`, 58 | ); 59 | } 60 | } 61 | } 62 | } 63 | 64 | /** 65 | * @function assertSpy 66 | * 67 | * Asserts the spy data. 68 | * 69 | * @param {Object} spy Spy object. 70 | * @param {number} callCount of times the spy was called. 71 | */ 72 | public static assertCall(spy: any, callCount: number) { 73 | assert.strictEqual( 74 | spy.callCount, 75 | callCount, 76 | 'Call count must match with the expected value.', 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /test/test_utils/Utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import * as Web3Utils from 'web3-utils'; 16 | 17 | import { Accounts } from 'web3-eth-accounts'; 18 | 19 | export default class Utils { 20 | public static generateRundomAddress(): string { 21 | const accounts = new Accounts(null); 22 | const account = accounts.create(Web3Utils.randomHex(32)); 23 | return account.address; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/test_utils/assert.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | import { ValidationErrorItem } from 'sequelize/types/lib/errors'; 18 | 19 | import chai = require('chai'); 20 | import chaiAsPromised = require('chai-as-promised'); 21 | chai.use(chaiAsPromised); 22 | const { assert } = chai; 23 | 24 | /** 25 | * It asserts the error message received from sequelize with the expected message. 26 | * @param errorObject Error object by sequelize. 27 | * @param messages Expected error messages. 28 | */ 29 | export function assertErrorMessages(errorObject: ValidationErrorItem[], messages: string[]): void { 30 | assert.strictEqual( 31 | errorObject.length, 32 | messages.length, 33 | `Error object has ${errorObject.length} errors but number of messages to be` 34 | + `asserted is ${messages.length}`, 35 | ); 36 | 37 | errorObject.forEach((value: ValidationErrorItem, index: number) => { 38 | assert.strictEqual( 39 | value.message, 40 | messages[index], 41 | ); 42 | }); 43 | } 44 | 45 | export default assert; 46 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/02_facilitator_start/01_start.test.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from 'child_process'; 2 | 3 | import SharedStorage from '../SharedStorage'; 4 | 5 | describe('facilitator start', async (): Promise => { 6 | it('should start facilitator', async (): Promise => { 7 | const helperObject = SharedStorage.getHelperObject(); 8 | const facilitatorStartScriptPath = helperObject.facilitatorStartScriptPath(); 9 | 10 | spawn( 11 | facilitatorStartScriptPath, 12 | { stdio: [process.stdout, process.stderr], env: process.env }, 13 | ); 14 | // Note: Ensuring that facilitator starts before doing any transactions. 15 | await new Promise(done => setTimeout(done, 30000)); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/05_facilitator_stop/01_stop.test.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process'; 2 | import * as path from 'path'; 3 | import fs from 'fs-extra'; 4 | import Directory from '../../../src/m0_facilitator/Directory'; 5 | import SharedStorage from '../SharedStorage'; 6 | 7 | const facilitatorKill = path.join(__dirname, '../kill_facilitator_process.sh'); 8 | 9 | describe('facilitator stop', async (): Promise => { 10 | it('should stop facilitator', async (): Promise => { 11 | execSync( 12 | facilitatorKill, 13 | { stdio: [process.stdout, process.stderr], env: process.env }, 14 | ); 15 | const testData = SharedStorage.getTestData(); 16 | fs.removeSync(Directory.getFacilitatorConfigPath( 17 | testData.originChain, 18 | testData.auxChainId, 19 | SharedStorage.getGatewayAddresses().eip20GatewayAddress, 20 | )); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/devchains.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | operation=$1 4 | originChain="dev-origin" 5 | auxiliaryChain="dev-auxiliary" 6 | 7 | function start_chains { 8 | 9 | echo starting $originChain chain 10 | ./node_modules/.bin/mosaic start $originChain 11 | sleep 10 12 | 13 | echo starting $auxiliaryChain chain 14 | ./node_modules/.bin/mosaic start $auxiliaryChain 15 | sleep 10 16 | 17 | } 18 | 19 | function stop_chains { 20 | echo stopping $originChain chain 21 | ./node_modules/.bin/mosaic stop $originChain 22 | 23 | echo stopping $auxiliaryChain chain 24 | ./node_modules/.bin/mosaic stop $auxiliaryChain 25 | } 26 | 27 | if [ $operation = "start" ]; then 28 | start_chains 29 | elif [ $operation = "stop" ]; then 30 | stop_chains 31 | else 32 | echo "invalid input" 33 | fi 34 | 35 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/helpers/BaseTokenHelper.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import * as path from 'path'; 19 | import BigNumber from 'bignumber.js'; 20 | import { HelperInterface } from './HelperInterface'; 21 | import Utils from '../Utils'; 22 | import { OSTPrime } from '@openst/mosaic-contracts/dist/interacts/OSTPrime'; 23 | import { TransactionObject } from '@openst/mosaic-contracts/dist/interacts/types'; 24 | import Logger from '../../../src/common/Logger'; 25 | 26 | export default class BaseTokenHelper implements HelperInterface { 27 | 28 | /** 29 | * @return path of script which performs facilitator init 30 | */ 31 | facilitatorInitScriptPath(): string { 32 | return path.join(__dirname, '../scripts/base_token/facilitator_init.sh'); 33 | } 34 | 35 | /** 36 | * @return path of script which performs facilitator start 37 | */ 38 | facilitatorStartScriptPath(): string { 39 | return path.join(__dirname, '../scripts/base_token/facilitator_start.sh'); 40 | } 41 | 42 | /** 43 | * Get minted balance, in this case OST Prime 44 | * @param beneficiary 45 | * @return balance of beneficiary 46 | */ 47 | getMintedBalance(beneficiary: string): Promise { 48 | const utils = new Utils(); 49 | return utils.getOSTPrimeBalance(beneficiary); 50 | } 51 | 52 | /** 53 | * gives Utility Token Instance, in this case OST Prime 54 | * @return 55 | */ 56 | getUtilityTokenInstance(): OSTPrime { 57 | const utils = new Utils(); 58 | return utils.getSimpleTokenPrimeInstance(); 59 | } 60 | 61 | /** 62 | * Perform Wrap to convert base currency of chain to corresponding EIP20 token 63 | * @param txOption extra data for executing tx 64 | * @return 65 | */ 66 | async wrapUtilityToken(txOption: any): Promise { 67 | Logger.debug('submitting wrapping OSTPrime tx.'); 68 | const wrapRawTx: TransactionObject = this.getUtilityTokenInstance().methods.wrap(); 69 | await Utils.sendTransaction( 70 | wrapRawTx, 71 | txOption, 72 | ); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/helpers/EIP20TokenHelper.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import * as path from 'path'; 19 | import BigNumber from 'bignumber.js'; 20 | import { UtilityToken } from '@openst/mosaic-contracts/dist/interacts/UtilityToken'; 21 | 22 | import { HelperInterface } from './HelperInterface'; 23 | import Utils from '../Utils'; 24 | import Logger from '../../../src/common/Logger'; 25 | 26 | export default class EIP20TokenHelper implements HelperInterface { 27 | 28 | /** 29 | * @return path of script which performs facilitator init 30 | */ 31 | facilitatorInitScriptPath(): string { 32 | return path.join(__dirname, '../scripts/eip20_token/facilitator_init.sh'); 33 | } 34 | 35 | /** 36 | * @return path of script which performs facilitator start 37 | */ 38 | facilitatorStartScriptPath(): string { 39 | return path.join(__dirname, '../scripts/eip20_token/facilitator_start.sh'); 40 | } 41 | 42 | /** 43 | * Get minted balance, in this case OST Prime 44 | * @param beneficiary 45 | * @return balance of beneficiary 46 | */ 47 | getMintedBalance(beneficiary: string): Promise { 48 | const utils = new Utils(); 49 | return utils.getUtilityTokenBalance(beneficiary); 50 | } 51 | 52 | /** 53 | * gives Utility Token Instance, in this case OST Prime 54 | * @return 55 | */ 56 | getUtilityTokenInstance(): UtilityToken { 57 | const utils = new Utils(); 58 | return utils.getUtilityTokenInstance(); 59 | } 60 | 61 | /** 62 | * Perform Wrap to convert base currency of chain to corresponding EIP20 token 63 | * Here it is not required 64 | * @param txOption extra data for executing tx 65 | * @return 66 | */ 67 | wrapUtilityToken(txOption: any): Promise { 68 | // Do nothing here 69 | Logger.debug('ignoring txOption for eip20Token', txOption); 70 | return new Promise(((resolve) => { 71 | resolve(); 72 | })); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/helpers/HelperInterface.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2019 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // ---------------------------------------------------------------------------- 16 | 17 | 18 | import BigNumber from 'bignumber.js'; 19 | import { OSTPrime } from '@openst/mosaic-contracts/dist/interacts/OSTPrime'; 20 | import { UtilityToken } from '@openst/mosaic-contracts/dist/interacts/UtilityToken'; 21 | 22 | /** 23 | * Integration tests run for BaseToken & EIP20Token 24 | * This interface defines methods which would implement logic which differs for the two cases 25 | * and are required for running integration tests 26 | */ 27 | export interface HelperInterface { 28 | 29 | /** 30 | * @return path of script which performs facilitator init 31 | */ 32 | facilitatorInitScriptPath(): string; 33 | 34 | /** 35 | * @return path of script which performs facilitator start 36 | */ 37 | facilitatorStartScriptPath(): string; 38 | 39 | /** 40 | * Get minted balance, in this case OST Prime 41 | * @param beneficiary 42 | * @return balance of beneficiary 43 | */ 44 | getMintedBalance(beneficiary: string): Promise; 45 | 46 | /** 47 | * gives Utility Token Instance, in this case OST Prime 48 | * @return 49 | */ 50 | getUtilityTokenInstance(): OSTPrime | UtilityToken; 51 | 52 | /** 53 | * Perform Wrap to convert base currency of chain to corresponding EIP20 token 54 | * @param txOption extra data for executing tx 55 | * @return 56 | */ 57 | wrapUtilityToken(txOption: any): Promise; 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/kill_facilitator_process.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | kill -TERM `ps aux | grep -e "[f]acilitator-start.ts[[:space:]]$ORIGIN_CHAIN[[:space:]]$AUXILIARY_CHAIN_ID\|[f]acilitator.ts[[:space:]]start[[:space:]]$ORIGIN_CHAIN[[:space:]]$AUXILIARY_CHAIN_ID\|[f]acilitator[[:space:]]start[[:space:]]$ORIGIN_CHAIN[[:space:]]$AUXILIARY_CHAIN_ID\|[f]acilitator_start.sh" | awk '{print $2}'` 3 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/base_token/deploy_subgraph.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | originChain="dev-origin" 4 | auxiliaryChain="dev-auxiliary" 5 | auxChainIdentifier="1000" 6 | originGraphAdminRPC="http://localhost:9535" 7 | originGraphIPFS="http://localhost:6516" 8 | auxiliaryGraphAdminRPC="http://localhost:9020" 9 | auxiliaryGraphIPFS="http://localhost:6001" 10 | 11 | echo deploying baseToken sub-graph for $originChain chain 12 | ./node_modules/.bin/mosaic subgraph $originChain $auxChainIdentifier origin $originGraphAdminRPC $originGraphIPFS 13 | sleep 10 14 | 15 | echo deploying baseToken sub-graph for $auxiliaryChain chain 16 | ./node_modules/.bin/mosaic subgraph $originChain $auxChainIdentifier auxiliary $auxiliaryGraphAdminRPC $auxiliaryGraphIPFS 17 | sleep 10 18 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/base_token/facilitator_init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./facilitator init --mosaic-config $MOSAIC_CONFIG_PATH --aux-chain-id $AUXILIARY_CHAIN_ID --origin-password $ORIGIN_WORKER_PASSWORD --auxiliary-password $AUXILIARY_WORKER_PASSWORD --origin-rpc $ORIGIN_RPC --auxiliary-rpc $AUXILIARY_RPC --origin-graph-ws $ORIGIN_GRAPH_WS --auxiliary-graph-ws $AUXILIARY_GRAPH_WS --origin-graph-rpc $ORIGIN_GRAPH_RPC --auxiliary-graph-rpc $AUXILIARY_GRAPH_RPC -f 3 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/base_token/facilitator_start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MOSAIC_FACILITATOR_LOG_LEVEL=debug ./facilitator start $ORIGIN_CHAIN $AUXILIARY_CHAIN_ID --mosaic-config $MOSAIC_CONFIG_PATH 4 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/eip20_token/deploy_subgraph.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | originChain="dev-origin" 4 | auxiliaryChain="dev-auxiliary" 5 | auxChainIdentifier="1000" 6 | ostGateway="0xae02c7b1c324a8d94a564bc8d713df89eae441fe" 7 | originGraphAdminRPC="http://localhost:9535" 8 | originGraphIPFS="http://localhost:6516" 9 | auxiliaryGraphAdminRPC="http://localhost:9020" 10 | auxiliaryGraphIPFS="http://localhost:6001" 11 | 12 | echo deploying eip20Token sub-graph for $originChain chain 13 | ./node_modules/.bin/mosaic subgraph $originChain $auxChainIdentifier origin $originGraphAdminRPC $originGraphIPFS -g $ostGateway 14 | sleep 10 15 | 16 | echo deploying eip20Token sub-graph for $auxiliaryChain chain 17 | ./node_modules/.bin/mosaic subgraph $originChain $auxChainIdentifier auxiliary $auxiliaryGraphAdminRPC $auxiliaryGraphIPFS -g $ostGateway 18 | sleep 10 19 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/eip20_token/facilitator_init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./facilitator init --gateway-config $GATEWAY_CONFIG_PATH --aux-chain-id $AUXILIARY_CHAIN_ID --origin-password $ORIGIN_WORKER_PASSWORD --auxiliary-password $AUXILIARY_WORKER_PASSWORD --origin-rpc $ORIGIN_RPC --auxiliary-rpc $AUXILIARY_RPC --origin-graph-ws $ORIGIN_GRAPH_WS --auxiliary-graph-ws $AUXILIARY_GRAPH_WS --origin-graph-rpc $ORIGIN_GRAPH_RPC --auxiliary-graph-rpc $AUXILIARY_GRAPH_RPC -f 3 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/scripts/eip20_token/facilitator_start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MOSAIC_FACILITATOR_LOG_LEVEL=debug ./facilitator start $ORIGIN_CHAIN $AUXILIARY_CHAIN_ID --gateway-config $GATEWAY_CONFIG_PATH 4 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/testdata/BaseToken.json: -------------------------------------------------------------------------------- 1 | { 2 | "auxChainId": 1000, 3 | "originChain": "dev-origin", 4 | "originWorkerExpirationHeight":"100000000000", 5 | "auxiliaryWorkerExpirationHeight":"100000000000", 6 | "originRpc":"http://127.0.0.1:41515", 7 | "originGraphRpc":"http://127.0.0.1:11515/subgraphs/name/mosaic/origin-A7f056b1320fE619571849f13", 8 | "originGraphWs":"ws://127.0.0.1:61515/subgraphs/name/mosaic/origin-A7f056b1320fE619571849f13", 9 | "originGraphAdminRPC": "http://localhost:9535", 10 | "originGraphIPFS": "http://localhost:6516", 11 | "auxiliaryRpc":"http://127.0.0.1:41000", 12 | "auxiliaryGraphRpc":"http://127.0.0.1:11000/subgraphs/name/mosaic/auxiliary-B6329BcFE2050F50db2eD3", 13 | "auxiliaryGraphWs":"ws://127.0.0.1:61000/subgraphs/name/mosaic/auxiliary-B6329BcFE2050F50db2eD3", 14 | "auxiliaryGraphAdminRPC": "http://localhost:9020", 15 | "auxiliaryGraphIPFS": "http://localhost:6001", 16 | "originWorkerPassword":"origin", 17 | "auxiliaryWorkerPassword":"auxiliary", 18 | "stakeAmount":"13000", 19 | "stakerValueTokenToFund": "20000", 20 | "redeemAmount":"1300", 21 | "redeemerOSTPrimeToFund": "10000000000000000", 22 | "gasPrice": "7", 23 | "gasLimit": "3" 24 | } 25 | -------------------------------------------------------------------------------- /test_integration/m0_facilitator/testdata/EIP20Token.json: -------------------------------------------------------------------------------- 1 | { 2 | "auxChainId": 1000, 3 | "originChain": "dev-origin", 4 | "originWorkerExpirationHeight":"100000000000", 5 | "auxiliaryWorkerExpirationHeight":"100000000000", 6 | "originRpc":"http://127.0.0.1:41515", 7 | "originGraphRpc":"http://127.0.0.1:11515/subgraphs/name/mosaic/origin-aE02C7b1C324A8D94A564bC8d", 8 | "originGraphWs":"ws://127.0.0.1:61515/subgraphs/name/mosaic/origin-aE02C7b1C324A8D94A564bC8d", 9 | "originGraphAdminRPC": "http://localhost:9535", 10 | "originGraphIPFS": "http://localhost:6516", 11 | "auxiliaryRpc":"http://127.0.0.1:41000", 12 | "auxiliaryGraphRpc":"http://127.0.0.1:11000/subgraphs/name/mosaic/auxiliary-c6fF898ceBf631eFb58eEc", 13 | "auxiliaryGraphWs":"ws://127.0.0.1:61000/subgraphs/name/mosaic/auxiliary-c6fF898ceBf631eFb58eEc", 14 | "auxiliaryGraphAdminRPC": "http://localhost:9020", 15 | "auxiliaryGraphIPFS": "http://localhost:6001", 16 | "originWorkerPassword":"origin", 17 | "auxiliaryWorkerPassword":"auxiliary", 18 | "stakeAmount":"13000", 19 | "stakerValueTokenToFund": "20000", 20 | "redeemAmount":"1300", 21 | "redeemerOSTPrimeToFund": "10000000000000000", 22 | "gasPrice": "7", 23 | "gasLimit": "3" 24 | } 25 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/02_subgraph_deployment/01_subgraph_deployment.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { execSync } from 'child_process'; 16 | import shared from '../shared'; 17 | import endpoints from '../endpoints'; 18 | 19 | describe('Deploy origin and auxiliary subgraph ', (): void => { 20 | it('should deploy origin subgraph', (): void => { 21 | const originAchorAddress = shared.contracts.originAnchor.address; 22 | const gatewayAddress = shared.contracts.erc20Gateway.address; 23 | const graphAdminRpcEndpoint = endpoints.origin.graph_rpc_admin; 24 | const ipfsEndpoint = endpoints.origin.ipfs; 25 | 26 | const command = `npm run deploy:subgraph:origin ${originAchorAddress} ${gatewayAddress} ${graphAdminRpcEndpoint} ${ipfsEndpoint}`; 27 | 28 | execSync( 29 | command, 30 | ); 31 | }); 32 | 33 | it('should deploy auxiliary subgraph', (): void => { 34 | const auxiliaryAchorAddress = shared.contracts.auxiliaryAnchor.address; 35 | const cogatewayAddress = shared.contracts.erc20Cogateway.address; 36 | const graphAdminRpcEndpoint = endpoints.auxilary.graph_rpc_admin; 37 | const ipfsEndpoint = endpoints.auxilary.ipfs; 38 | 39 | const command = `npm run deploy:subgraph:auxiliary ${auxiliaryAchorAddress} ${cogatewayAddress} ${graphAdminRpcEndpoint} ${ipfsEndpoint}`; 40 | 41 | execSync(command); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/03_facilitator_init/01_facilitator_init.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { execSync } from 'child_process'; 16 | import jsYaml from 'js-yaml'; 17 | import fs from 'fs'; 18 | import * as web3Utils from 'web3-utils'; 19 | 20 | import path from 'path'; 21 | import generateFacilitatorManifest from './FacilitatorManifestGenerator'; 22 | import shared from '../shared'; 23 | 24 | describe('Facilitator init ', (): void => { 25 | it('should perform facilitator init', async (): Promise => { 26 | const manifestFilePath = path.join(__dirname, '..', 'manifest.yaml'); 27 | const executablePath = path.join(__dirname, '..', '..', '..'); 28 | const command = `sh ${executablePath}/facilitator_m1 init --manifest ${manifestFilePath} -f`; 29 | const manifest = generateFacilitatorManifest(shared); 30 | fs.writeFileSync(manifestFilePath, jsYaml.dump(manifest)); 31 | execSync(command, { 32 | cwd: executablePath, 33 | stdio: ['inherit', 'inherit', 'inherit'], 34 | }); 35 | 36 | const originAvatar = manifest.metachain.origin.avatar_account; 37 | const auxiliaryAvatar = manifest.metachain.auxiliary.avatar_account; 38 | 39 | // Funding facilitator avatar account 40 | await shared.origin.web3.eth.sendTransaction( 41 | { 42 | from: shared.origin.deployer, 43 | to: originAvatar, 44 | value: web3Utils.toWei('1', 'ether'), 45 | }, 46 | ); 47 | // Funding facilitator avatar account 48 | await shared.auxiliary.web3.eth.sendTransaction( 49 | { 50 | from: shared.auxiliary.deployer, 51 | to: auxiliaryAvatar, 52 | value: web3Utils.toWei('1', 'ether'), 53 | }, 54 | ); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/03_facilitator_init/FacilitatorManifestGenerator.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | import { 17 | ArchitectureLayout, 18 | Personas, 19 | } from '../../../src/m1_facilitator/manifest/Manifest'; 20 | import endpoints from '../endpoints'; 21 | import { Shared } from '../shared'; 22 | 23 | const generateFacilitatorManifest = (shared: Shared) => ({ 24 | version: 'v0.14', 25 | architecture_layout: ArchitectureLayout.MOSAIC_0_14_GEN_1, 26 | personas: [Personas.FACILITATOR], 27 | metachain: 28 | { 29 | origin: 30 | { 31 | avatar_account: '0x296a65814a2c07bf7a8ee310a212a4796dc0123a', 32 | node_endpoint: endpoints.origin.chain, 33 | graph_ws_endpoint: `${endpoints.origin.graph_ws}/subgraphs/name/mosaic/origin-erc20gateway`, 34 | graph_rpc_endpoint: `${endpoints.origin.graph_rpc}/subgraphs/name/mosaic/origin-erc20gateway`, 35 | }, 36 | auxiliary: 37 | { 38 | avatar_account: '0x61bd2fd5c5ebb902b2b86d13f0b00b353ceec017', 39 | node_endpoint: endpoints.auxilary.chain, 40 | graph_ws_endpoint: `${endpoints.auxilary.graph_ws}/subgraphs/name/mosaic/aux-erc20gateway`, 41 | graph_rpc_endpoint: `${endpoints.auxilary.graph_rpc}/subgraphs/name/mosaic/aux-erc20gateway`, 42 | }, 43 | }, 44 | accounts: 45 | { 46 | '0x296a65814a2c07bf7a8ee310a212a4796dc0123a': 47 | { 48 | keystore_path: 'testdata/m1_facilitator/origin_keystore.json', 49 | keystore_password_path: 'testdata/m1_facilitator/origin_password', 50 | }, 51 | '0x61bd2fd5c5ebb902b2b86d13f0b00b353ceec017': 52 | { 53 | keystore_path: 'testdata/m1_facilitator/aux_keystore.json', 54 | keystore_password_path: 'testdata/m1_facilitator/aux_password', 55 | }, 56 | }, 57 | origin_contract_addresses: { erc20_gateway: shared.contracts.erc20Gateway.address }, 58 | facilitate_tokens: [], 59 | 60 | }); 61 | 62 | export default generateFacilitatorManifest; 63 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/04_facilitator_start/01_facilitator_start.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import path from 'path'; 16 | import fs from 'fs'; 17 | import jsYaml from 'js-yaml'; 18 | import { spawn } from 'child_process'; 19 | import shared from '../shared'; 20 | import generateFacilitatorManifest 21 | from '../03_facilitator_init/FacilitatorManifestGenerator'; 22 | 23 | describe('Start facilitator', async (): Promise => { 24 | it('should start facilitator', async (): Promise => { 25 | const manifestFilePath = path.join(__dirname, '..', 'manifest.yaml'); 26 | const executablePath = path.join(__dirname, '..', '..', '..'); 27 | const command = `sh ${executablePath}/facilitator_m1 start --manifest ${manifestFilePath}`; 28 | 29 | const manifest = generateFacilitatorManifest(shared); 30 | fs.writeFileSync(manifestFilePath, jsYaml.dump(manifest)); 31 | spawn(command, [], { 32 | cwd: executablePath, 33 | stdio: ['inherit', 'inherit', 'inherit'], 34 | shell: true, 35 | }); 36 | 37 | // Note: Ensuring that facilitator starts before doing any transactions. 38 | await new Promise(done => setTimeout(done, 30000)); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/07_facilitator_stop/01_facilitator_stop.test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import path from 'path'; 16 | import { execSync } from 'child_process'; 17 | 18 | describe('Facilitator stop ', (): void => { 19 | it('should stop facilitator', (): void => { 20 | const killFacilitator = path.join(__dirname, '..', 'kill_facilitator_process.sh'); 21 | execSync( 22 | ` sh ${killFacilitator}`, 23 | { stdio: [process.stdout, process.stderr], env: process.env }, 24 | ); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | graph_node_origin: 4 | image: graphprotocol/graph-node:v0.16.0 5 | ports: 6 | - '8000:8000' 7 | - '8001:8001' 8 | - '8020:8020' 9 | depends_on: 10 | - postgres_origin 11 | - ipfs 12 | - geth_node_origin 13 | environment: 14 | postgres_host: postgres_origin:5432 15 | postgres_user: 'postgres' 16 | postgres_pass: 'postgres' 17 | postgres_db: 'mosaic_origin' 18 | ipfs: 'ipfs:5001' 19 | ethereum: '${origin_ethereum}' 20 | RUST_LOG: info 21 | GRAPH_LOG: info 22 | ETHEREUM_POLLING_INTERVAL: 3000 23 | ETHEREUM_REORG_THRESHOLD: 0 24 | geth_node_origin: 25 | image: augurproject/dev-node-geth:v1.9.9 26 | ports: 27 | - "8546:8545" 28 | postgres_origin: 29 | image: postgres:alpine 30 | ports: 31 | - '6432:5432' 32 | environment: 33 | POSTGRES_USER: 'postgres' 34 | POSTGRES_PASSWORD: 'postgres' 35 | POSTGRES_DB: 'mosaic_origin' 36 | ipfs: 37 | image: ipfs/go-ipfs:v0.4.22-rc1 38 | ports: 39 | - '5001:5001' 40 | graph_node_auxiliary: 41 | image: graphprotocol/graph-node:v0.16.0 42 | ports: 43 | - '9000:8000' 44 | - '9001:8001' 45 | - '9020:8020' 46 | depends_on: 47 | - postgres_auxiliary 48 | - ipfs 49 | - geth_node_auxiliary 50 | environment: 51 | postgres_host: postgres_auxiliary:5432 52 | postgres_user: 'postgres' 53 | postgres_pass: 'postgres' 54 | postgres_db: 'mosaic_auxiliary' 55 | ipfs: 'ipfs:5001' 56 | ethereum: '${auxiliary_ethereum}' 57 | RUST_LOG: info 58 | GRAPH_LOG: info 59 | ETHEREUM_POLLING_INTERVAL: 3000 60 | ETHEREUM_REORG_THRESHOLD: 0 61 | geth_node_auxiliary: 62 | image: augurproject/dev-node-geth:v1.9.9 63 | ports: 64 | - "9546:8545" 65 | postgres_auxiliary: 66 | image: postgres:alpine 67 | ports: 68 | - '7432:5432' 69 | environment: 70 | POSTGRES_USER: 'postgres' 71 | POSTGRES_PASSWORD: 'postgres' 72 | POSTGRES_DB: 'mosaic_auxiliary' 73 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/docker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import waitPort = require('wait-port'); 16 | 17 | const originPort = 8546; 18 | const auxiliaryPort = 9546; 19 | 20 | const asyncSleep = async (ms: number): Promise => new Promise( 21 | resolve => setTimeout(resolve, ms), 22 | ); 23 | 24 | const docker = async (): Promise<{ 25 | rpcEndpointOrigin: string; 26 | rpcEndpointAuxiliary: string; 27 | }> => { 28 | // @ts-ignore 29 | const waitForOriginNode = waitPort({ port: originPort, output: 'silent' }); 30 | // @ts-ignore 31 | const waitForAuxiliaryNode = waitPort({ port: auxiliaryPort, output: 'silent' }); 32 | return Promise.all([waitForOriginNode, waitForAuxiliaryNode]).then( 33 | // even after the ports are available the nodes need a bit of time to get online 34 | async () => asyncSleep(5000), 35 | ).then(() => ({ 36 | rpcEndpointOrigin: `http://localhost:${originPort}`, 37 | rpcEndpointAuxiliary: `http://localhost:${auxiliaryPort}`, 38 | })); 39 | }; 40 | 41 | export default docker; 42 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/endpoints.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | origin: { 3 | chain: 'http://localhost:8546', 4 | graph_rpc_admin: 'http://localhost:8020', 5 | graph_rpc: 'http://localhost:8000', 6 | graph_ws: 'ws://localhost:8001', 7 | ipfs: 'http://localhost:5001', 8 | }, 9 | auxilary: { 10 | chain: 'http://localhost:9546', 11 | graph_rpc_admin: 'http://localhost:9020', 12 | graph_rpc: 'http://localhost:9000', 13 | graph_ws: 'ws://localhost:9001', 14 | ipfs: 'http://localhost:5001', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/kill_facilitator_process.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | kill -TERM `ps aux | grep -e "[f]acilitator-start.ts" | awk '{print $2}'` 3 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/main.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | IP=`ifconfig ${NEaT_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | grep -v '172*'` 4 | 5 | origin_ethereum=dev:http://${IP}:8546 auxiliary_ethereum=dev:http://${IP}:9546 docker-compose up & 6 | sleep 1m 7 | mocha -t 1800000 --require ts-node/register --require source-map-support/register --recursive ./**/*.test.ts 8 | TEST_STATUS=$? 9 | docker-compose down 10 | exit $TEST_STATUS 11 | -------------------------------------------------------------------------------- /test_integration/m1_facilitator/shared.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import Web3 from 'web3'; 16 | import { Anchor } from 'Mosaic/dist/interacts/Anchor'; 17 | import { ERC20Gateway } from 'Mosaic/dist/interacts/ERC20Gateway'; 18 | import { UtilityToken } from 'Mosaic/dist/interacts/UtilityToken'; 19 | import { Gen0ERC20Cogateway } from 'Mosaic/dist/interacts/Gen0ERC20Cogateway'; 20 | import { ERC20I } from 'Mosaic/dist/interacts/ERC20I'; 21 | 22 | // eslint-disable no-object-literal-type-assertion 23 | class Chain { 24 | public web3: Web3; 25 | 26 | public accounts: string[]; 27 | 28 | public deployer: string; 29 | 30 | 31 | public constructor() { 32 | this.web3 = new Web3(''); 33 | this.accounts = []; 34 | this.deployer = ''; 35 | } 36 | } 37 | 38 | class Contract { 39 | public originAnchor: Anchor; 40 | 41 | public auxiliaryAnchor: Anchor; 42 | 43 | public erc20Gateway: ERC20Gateway; 44 | 45 | public erc20Cogateway: Gen0ERC20Cogateway; 46 | 47 | public utilityTokenMasterCopy: UtilityToken; 48 | 49 | public valueToken: ERC20I; 50 | 51 | public constructor() { 52 | this.originAnchor = {} as Anchor; 53 | this.auxiliaryAnchor = {} as Anchor; 54 | this.erc20Gateway = {} as ERC20Gateway; 55 | this.erc20Cogateway = {} as Gen0ERC20Cogateway; 56 | this.utilityTokenMasterCopy = {} as UtilityToken; 57 | // eslint-disable-next-line no-object-literal-type-assertion 58 | this.valueToken = {} as ERC20I; 59 | } 60 | } 61 | 62 | export class Shared { 63 | public origin: Chain; 64 | 65 | public auxiliary: Chain; 66 | 67 | public contracts: Contract; 68 | 69 | public anchorConsensusAddress: string; 70 | 71 | public anchorCoconsensusAddress: string; 72 | 73 | public metachainId: string; 74 | 75 | public constructor() { 76 | this.origin = new Chain(); 77 | this.auxiliary = new Chain(); 78 | this.contracts = new Contract(); 79 | this.anchorConsensusAddress = ''; 80 | this.anchorCoconsensusAddress = ''; 81 | this.metachainId = ''; 82 | } 83 | } 84 | 85 | export default new Shared(); 86 | -------------------------------------------------------------------------------- /testdata/m0_facilitator/0xae02c7b1c324a8d94a564bc8d713df89eae441fe.json: -------------------------------------------------------------------------------- 1 | { 2 | "mosaicConfigFilePath":"./testdata/m0_facilitator/mosaic.json", 3 | "auxChainId":1000, 4 | "originContracts":{ 5 | "baseTokenAddress":"0x9AC77F4c0ca4D0F2142D7a77175cf4F1295fb2d8", 6 | "valueTokenAddress":"0x8e183Fd2cd55C7C05bBf4FAC989740f69e559A6d", 7 | "gatewayOrganizationAddress":"0x3f99f42d226A0CD1C1Fcae1e8dC11b2f7a9DcE4B", 8 | "eip20GatewayAddress":"0xaE02C7b1C324A8D94A564bC8d713Df89eae441fe" 9 | }, 10 | "auxiliaryContracts":{ 11 | "coGatewayOrganizationAddress":"0x2D586C7E220839a9284888B10aDF4823AcD6EdF3", 12 | "utilityTokenAddress":"0x62F8729C1C282C231a22252e90CE9735533D2518", 13 | "eip20CoGatewayAddress":"0xc6fF898ceBf631eFb58eEc7187E4c1f70AE8d943" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /testdata/m1_facilitator/aux_keystore.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "94724d75-bc1a-4958-afcc-33700264aaa1", 4 | "address": "61bd2fd5c5ebb902b2b86d13f0b00b353ceec017", 5 | "crypto": { 6 | "ciphertext": "4a7357807354e85b2837d4b56f8b7ece876bafd9f0d4cad7e762e0ee08948436", 7 | "cipherparams": { 8 | "iv": "3c42bcfbcd3bea1194ddc71fd759b493" 9 | }, 10 | "cipher": "aes-128-ctr", 11 | "kdf": "scrypt", 12 | "kdfparams": { 13 | "dklen": 32, 14 | "salt": "813aa3e4e1de27a1baf741c0d6a22f0e6013707106b0f8b6660c4455d795d7f9", 15 | "n": 8192, 16 | "r": 8, 17 | "p": 1 18 | }, 19 | "mac": "860e58ced14d02c06b9faafa0174b1fac257fd521f3c236d3fd782aae5865c1a" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /testdata/m1_facilitator/aux_password: -------------------------------------------------------------------------------- 1 | password -------------------------------------------------------------------------------- /testdata/m1_facilitator/facilitator_manifest.yml: -------------------------------------------------------------------------------- 1 | version: v0.14 2 | architecture_layout: MOSAIC_0_14_GEN_1 3 | personas: 4 | - facilitator 5 | metachain: 6 | origin: 7 | avatar_account: "0xac7E36b3cdDb14Bf1c67dC21fFB24C73d03d8FF7" 8 | node_endpoint: https://localhost:8545 9 | graph_ws_endpoint: ws://localhost:8000/subgraphs/name/m1_facilitator 10 | graph_rpc_endpoint: http://localhost:8000/subgraphs/name/m1_facilitator 11 | auxiliary: 12 | avatar_account: "0x81Df1244dEd6EF44a90a67526E4Ec4497d807F96" 13 | node_endpoint: https://localhost.com:8645 14 | graph_ws_endpoint: ws://localhost:8000/subgraphs/name/m1_facilitator 15 | graph_rpc_endpoint: http://localhost:8000/subgraphs/name/m1_facilitator 16 | accounts: 17 | "0xac7E36b3cdDb14Bf1c67dC21fFB24C73d03d8FF7": 18 | keystore_path: "testdata/m1_facilitator/origin_keystore.json" 19 | keystore_password_path: "testdata/m1_facilitator/origin_password" 20 | "0x81Df1244dEd6EF44a90a67526E4Ec4497d807F96": 21 | keystore_path: "testdata/m1_facilitator/aux_keystore.json" 22 | keystore_password_path: "testdata/m1_facilitator/aux_password" 23 | origin_contract_addresses: 24 | erc20_gateway: "0xA7f056b1320fE619571849f138Cd1Ae2f2e64179" 25 | facilitate_tokens: 26 | - "0x9aC77F4c0ca4D0F2142D7a77175cf4F1295fb2d8" 27 | - "0x19F64B29789F02FFcCE2c37DFB3d65FEaDdea66a" 28 | -------------------------------------------------------------------------------- /testdata/m1_facilitator/origin_keystore.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "id": "afa6fcef-a3cb-4dfe-88c4-c20998d824a8", 4 | "address": "296a65814a2c07bf7a8ee310a212a4796dc0123a", 5 | "crypto": { 6 | "ciphertext": "fd870df2b7e37aa70bbdc87e649bd5a73cdf1e28d8528e59a7c85c248f7791b2", 7 | "cipherparams": { 8 | "iv": "08f888a1b3d99d052fd0c8f256de3118" 9 | }, 10 | "cipher": "aes-128-ctr", 11 | "kdf": "scrypt", 12 | "kdfparams": { 13 | "dklen": 32, 14 | "salt": "b8af0a30ef8ca88a74954ac6bbe6b90253d0da180847904e8d1ccb2f469861cc", 15 | "n": 8192, 16 | "r": 8, 17 | "p": 1 18 | }, 19 | "mac": "921548a25e50de3d51ec5d8eb3d03abd75ebbe023e7a4f68153c409e73d57392" 20 | } 21 | } -------------------------------------------------------------------------------- /testdata/m1_facilitator/origin_password: -------------------------------------------------------------------------------- 1 | password -------------------------------------------------------------------------------- /testnet/m1_facilitator/fund_facilitator/FundFacilitatorAccount.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import axios from 'axios'; 16 | import BigNumber from 'bignumber.js'; 17 | import Logger from '../../../src/common/Logger'; 18 | import Web3 from 'web3'; 19 | import Command from '../../../src/m1_facilitator/commands/Command'; 20 | import Manifest from '../../../src/m1_facilitator/manifest/Manifest'; 21 | 22 | // Threshold amount in atto below which facilitator account will be funded from faucet. 23 | const FACILITATOR_ACCOUNT_THRESHOLD = new BigNumber('1000000000000000000'); 24 | 25 | const FAUCET_URL = 'https://faucet.mosaicdao.org'; 26 | 27 | const HADAPSAR = '1405'; 28 | 29 | /* 30 | * Returns balance of facilitator account in atto. 31 | */ 32 | async function checkBalance(account: string, web3: Web3): Promise { 33 | const accountBalance = await web3.eth.getBalance(account); 34 | return new BigNumber(accountBalance); 35 | } 36 | 37 | export default class FundFacilitatorAccount implements Command { 38 | private manifestPath: string; 39 | 40 | /** 41 | * Construct FundFacilitatorAccount instance with params. 42 | * 43 | * @param manifestPath Path of manifest file. 44 | */ 45 | public constructor(manifestPath: string) { 46 | this.manifestPath = manifestPath; 47 | } 48 | 49 | /** 50 | * Executes fund_facilitator_account command. 51 | */ 52 | public async execute(): Promise { 53 | const manifest = Manifest.fromFile(this.manifestPath); 54 | const account = manifest.metachain.auxiliaryChain.avatarAccount; 55 | if ((await checkBalance(account, manifest.metachain.auxiliaryChain.web3)) 56 | .lt(FACILITATOR_ACCOUNT_THRESHOLD)) { 57 | const result = await axios.post( 58 | FAUCET_URL, 59 | { 60 | beneficiary: `${account}@${HADAPSAR}`, 61 | }, 62 | ); 63 | Logger.info(`Transaction hash is ${result.data.txHash}`); 64 | Logger.info(`https://view.mosaicdao.org/tx/${result.data.txHash}/internal_transactions`); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /testnet/m1_facilitator/fund_facilitator/bin/fund-facilitator-account.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 OpenST Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import fund_facilitator_account from 'commander'; 16 | import FundFacilitatorAccount from '../FundFacilitatorAccount'; 17 | import Logger from '../../../../src/common/Logger'; 18 | 19 | 20 | /** 21 | * To execute fund_facilitator_account command, 22 | * ./fund_facilitator_account -m 23 | */ 24 | fund_facilitator_account.option('-m, --manifest ', 'Path to manifest file') 25 | .action( 26 | async ( 27 | options: { 28 | manifest: string; 29 | }): Promise => { 30 | try { 31 | await new FundFacilitatorAccount(options.manifest).execute(); 32 | } catch (e) { 33 | Logger.error(`Error in fund_facilitator_account command. Reason: ${e.message}`); 34 | process.exit(1); 35 | } 36 | }, 37 | ).parse(process.argv); 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2016", 4 | "module": "commonjs", 5 | "outDir": "./lib", 6 | "allowSyntheticDefaultImports": true, 7 | "esModuleInterop": true, 8 | "alwaysStrict": true, 9 | "strictNullChecks": true, 10 | "strictBindCallApply": true, 11 | "strictFunctionTypes": true, 12 | "strictPropertyInitialization": true, 13 | "noImplicitThis": true, 14 | "noImplicitAny": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noErrorTruncation": true, 20 | "resolveJsonModule": true, 21 | "inlineSourceMap": true, 22 | "declaration": true, 23 | "types": [ 24 | "chai", 25 | "node", 26 | "mocha", 27 | "web3", 28 | "sinon" 29 | ] 30 | }, 31 | "include": [ 32 | "index.ts", 33 | "src/*.ts", 34 | "src/**/*.ts", 35 | "src/**/**/*.ts" 36 | ], 37 | "exclude": [ 38 | "node_modules" 39 | ] 40 | } 41 | --------------------------------------------------------------------------------