├── .dockerignore
├── .env.example
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── bug_report_mobile.md
│ ├── bug_report_web.md
│ └── new-feature.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── ci.yaml
│ ├── dmw_test.yaml
│ └── e2e.yaml
├── .gitignore
├── .gitmodules
├── .pyre_configuration
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── backend
├── .env.example
├── Dockerfile
├── MANIFEST.in
├── Pipfile
├── Pipfile.lock
├── README.md
├── context
│ ├── __init__.py
│ ├── config.py
│ ├── context.py
│ └── stubs
│ │ ├── __init__.py
│ │ └── custody.py
├── diem_utils
│ ├── __init__.py
│ ├── _version.py
│ ├── custody.py
│ ├── precise_amount.py
│ ├── sdks
│ │ ├── __init__.py
│ │ └── liquidity.py
│ ├── types
│ │ ├── __init__.py
│ │ ├── currencies.py
│ │ └── liquidity
│ │ │ ├── __init__.py
│ │ │ ├── currency.py
│ │ │ ├── errors.py
│ │ │ ├── lp.py
│ │ │ ├── quote.py
│ │ │ ├── settlement.py
│ │ │ └── trade.py
│ └── vasp.py
├── offchain
│ ├── __init__.py
│ ├── action.py
│ ├── client.py
│ ├── command.py
│ ├── error.py
│ ├── funds_pull_pre_approval_command.py
│ ├── funds_pull_pre_approval_command_state.py
│ ├── http_header.py
│ ├── http_server.py
│ ├── jws.py
│ ├── payment_command.py
│ ├── payment_state.py
│ ├── state.py
│ └── types
│ │ ├── __init__.py
│ │ ├── cid.py
│ │ ├── command_types.py
│ │ ├── fund_pull_pre_approval_types.py
│ │ ├── p2m_payment_types.py
│ │ └── p2p_payment_types.py
├── pubsub
│ ├── __init__.py
│ ├── __main__.py
│ ├── client.py
│ └── types.py
├── run_pubsub.sh
├── run_web.sh
├── run_worker.sh
├── setup.py
├── test.sh
├── tests
│ ├── README.md
│ ├── __init__.py
│ ├── conftest.py
│ ├── context_tests
│ │ ├── test_config.py
│ │ ├── test_context.py
│ │ └── test_custody.py
│ ├── e2e_tests
│ │ ├── __init__.py
│ │ ├── double
│ │ │ ├── __init__.py
│ │ │ ├── test_p2m_payments.py
│ │ │ └── test_p2p_payments.py
│ │ └── single
│ │ │ ├── __init__.py
│ │ │ └── test_init.py
│ ├── mw_drw_proxy
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── helpers.py
│ │ └── proxy.py
│ ├── offchain_tests
│ │ ├── test_deserialize.py
│ │ └── test_offchain_state.py
│ ├── pubsub_tests
│ │ ├── __init__.py
│ │ └── test_client.py
│ ├── setup.py
│ ├── wallet_tests
│ │ ├── __init__.py
│ │ ├── client_sdk_mocks.py
│ │ ├── conftest.py
│ │ ├── liquidity
│ │ │ ├── __init__.py
│ │ │ ├── client
│ │ │ │ ├── __init__.py
│ │ │ │ └── test_client.py
│ │ │ ├── test_amount.py
│ │ │ └── test_utils.py
│ │ ├── resources
│ │ │ ├── __init__.py
│ │ │ └── seeds
│ │ │ │ ├── __init__.py
│ │ │ │ ├── add_funds_seeder.py
│ │ │ │ ├── balances_seeder.py
│ │ │ │ ├── convert_seeder.py
│ │ │ │ ├── one_approved_user.py
│ │ │ │ ├── one_funds_pull_pre_approval.py
│ │ │ │ ├── one_p2m_payment_seeder.py
│ │ │ │ ├── one_p2p_payment_seeder.py
│ │ │ │ ├── one_user_multiple_transactions.py
│ │ │ │ ├── one_user_seeder.py
│ │ │ │ ├── one_user_with_one_order.py
│ │ │ │ ├── prototypes.py
│ │ │ │ └── withdraw_funds_seeder.py
│ │ ├── services
│ │ │ ├── __init__.py
│ │ │ ├── fx
│ │ │ │ ├── __init__.py
│ │ │ │ └── test_fx.py
│ │ │ ├── offchain
│ │ │ │ ├── test_fppa_process_inbound_request.py
│ │ │ │ ├── test_fund_pull_pre_approval.py
│ │ │ │ ├── test_offchain.py
│ │ │ │ ├── test_p2m_payment.py
│ │ │ │ ├── test_p2m_payment_as_receiver.py
│ │ │ │ └── test_p2p_payment.py
│ │ │ ├── system
│ │ │ │ ├── test_add_incoming_transaction_from_blockchain.py
│ │ │ │ ├── test_add_outgoing_transaction_from_blockchain.py
│ │ │ │ ├── test_calculate_lrw_balance.py
│ │ │ │ ├── test_remove_incoming_transaction_from_db.py
│ │ │ │ ├── test_remove_outgoing_transaction_from_db.py
│ │ │ │ ├── test_subaddreses_from_metadata.py
│ │ │ │ ├── test_sync_multiple_transactions.py
│ │ │ │ ├── test_sync_transaction_method.py
│ │ │ │ ├── test_sync_until_specific_version.py
│ │ │ │ ├── test_sync_when_no_data_in_blockchain.py
│ │ │ │ ├── test_sync_with_empty_db.py
│ │ │ │ └── utils.py
│ │ │ ├── test_account.py
│ │ │ ├── test_order.py
│ │ │ ├── test_transaction.py
│ │ │ ├── test_user.py
│ │ │ └── test_validation_tool.py
│ │ ├── storage
│ │ │ ├── __init__.py
│ │ │ ├── test_fund_pull_pre_approval.py
│ │ │ ├── test_order.py
│ │ │ ├── test_transaction.py
│ │ │ └── test_user.py
│ │ ├── test_risk.py
│ │ └── test_security.py
│ └── webapp_tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ └── routes
│ │ ├── test_account.py
│ │ ├── test_admin.py
│ │ ├── test_cico.py
│ │ ├── test_fund_pull_pre_approval.py
│ │ ├── test_p2m_payment.py
│ │ ├── test_p2p_payment.py
│ │ ├── test_rates.py
│ │ ├── test_user.py
│ │ └── test_validation_tool.py
├── wallet
│ ├── __init__.py
│ ├── background_tasks
│ │ ├── __init__.py
│ │ ├── background.py
│ │ └── utils.py
│ ├── config.py
│ ├── logging.py
│ ├── security.py
│ ├── services
│ │ ├── __init__.py
│ │ ├── account.py
│ │ ├── fx
│ │ │ ├── __init__.py
│ │ │ └── fx.py
│ │ ├── inventory.py
│ │ ├── kyc.py
│ │ ├── log.py
│ │ ├── offchain
│ │ │ ├── __init__.py
│ │ │ ├── fund_pull_pre_approval.py
│ │ │ ├── fund_pull_pre_approval_sm.py
│ │ │ ├── offchain.py
│ │ │ ├── p2m_payment.py
│ │ │ ├── p2m_payment_as_receiver.py
│ │ │ ├── p2p_payment.py
│ │ │ ├── p2p_payment_as_receiver.py
│ │ │ └── utils.py
│ │ ├── order.py
│ │ ├── risk.py
│ │ ├── system.py
│ │ ├── transaction.py
│ │ ├── user.py
│ │ └── validation_tool.py
│ ├── storage
│ │ ├── __init__.py
│ │ ├── account.py
│ │ ├── funds_pull_pre_approval_command.py
│ │ ├── logs.py
│ │ ├── models.py
│ │ ├── order.py
│ │ ├── p2m_payment.py
│ │ ├── p2p_payment.py
│ │ ├── setup.py
│ │ ├── token.py
│ │ ├── transaction.py
│ │ └── user.py
│ └── types.py
└── webapp
│ ├── __init__.py
│ ├── debug.py
│ ├── errors.py
│ ├── openapi.yaml
│ ├── routes
│ ├── __init__.py
│ ├── account.py
│ ├── admin.py
│ ├── cico.py
│ ├── offchain
│ │ ├── funds_pull_pre_approval.py
│ │ ├── main_offchain.py
│ │ ├── p2m_payment.py
│ │ └── p2p_payment.py
│ ├── strict_schema_view.py
│ ├── system.py
│ ├── user.py
│ └── validation_tool.py
│ ├── schemas.py
│ ├── static
│ └── favicon.ico
│ ├── swagger.py
│ └── templates
│ └── execution_logs.html
├── docker
├── debug.docker-compose.yaml
├── dev.docker-compose.yaml
├── docker-compose.yaml
├── e2e.docker-compose.yaml
├── pg
│ ├── Dockerfile
│ └── init.d
│ │ └── backend.sh
└── static.docker-compose.yaml
├── format.sh
├── frontend
├── .dockerignore
├── .env.example
├── .gitignore
├── Dockerfile
├── README.md
├── package.json
├── public
│ ├── favicon.png
│ ├── index.html
│ └── robots.txt
├── src
│ ├── App.tsx
│ ├── assets
│ │ ├── fonts
│ │ │ └── freesans
│ │ │ │ ├── FreeSans.woff
│ │ │ │ ├── FreeSansBold.woff
│ │ │ │ ├── FreeSansBoldOblique.woff
│ │ │ │ ├── FreeSansOblique.woff
│ │ │ │ └── style.css
│ │ ├── img
│ │ │ ├── close.svg
│ │ │ ├── currency-circle-libra-eur.svg
│ │ │ ├── currency-circle-libra-gbp.svg
│ │ │ ├── currency-circle-libra-usd.svg
│ │ │ ├── currency-circle-libra.svg
│ │ │ ├── gears.svg
│ │ │ ├── logo.svg
│ │ │ └── qr.svg
│ │ └── scss
│ │ │ ├── _credit-cards.scss
│ │ │ ├── _variables.scss
│ │ │ └── main.scss
│ ├── components
│ │ ├── Actions.tsx
│ │ ├── Balance.tsx
│ │ ├── BalancesList.tsx
│ │ ├── Breadcrumbs.tsx
│ │ ├── CloseButton.tsx
│ │ ├── ConfirmationModal.tsx
│ │ ├── ExampleSectionWarning.tsx
│ │ ├── ExplorerLink.tsx
│ │ ├── Feedback.tsx
│ │ ├── FundsPullPreApproval
│ │ │ ├── ApprovalDetails.tsx
│ │ │ ├── ApproveModal.tsx
│ │ │ ├── FundsPullPreApproval.tsx
│ │ │ ├── FundsPullPreApprovalsList.tsx
│ │ │ ├── RejectModal.tsx
│ │ │ └── RevokeModal.tsx
│ │ ├── Header.tsx
│ │ ├── LegalDisclaimer.tsx
│ │ ├── Messages
│ │ │ ├── ErrorMessage.tsx
│ │ │ ├── InfoMessage.tsx
│ │ │ └── SuccessMessage.tsx
│ │ ├── PaymentConfirmation.tsx
│ │ ├── PaymentConfirmationModal.tsx
│ │ ├── ReceiveModal.tsx
│ │ ├── Send
│ │ │ ├── SendForm.tsx
│ │ │ ├── SendModal.tsx
│ │ │ ├── SendReview.tsx
│ │ │ └── interfaces.ts
│ │ ├── Settings
│ │ │ ├── BackAccountForm.tsx
│ │ │ ├── CreditCardForm.tsx
│ │ │ ├── PaymentMethodsForm.tsx
│ │ │ └── PreferencesForm.tsx
│ │ ├── SettlementDetails.tsx
│ │ ├── SignedUpMessage.tsx
│ │ ├── TestnetWarning.tsx
│ │ ├── TotalBalance.tsx
│ │ ├── TransactionModal.tsx
│ │ ├── TransactionsList.tsx
│ │ ├── Transfer
│ │ │ ├── Convert.tsx
│ │ │ ├── ConvertForm.tsx
│ │ │ ├── ConvertReview.tsx
│ │ │ ├── Deposit.tsx
│ │ │ ├── DepositForm.tsx
│ │ │ ├── DepositReview.tsx
│ │ │ ├── Withdraw.tsx
│ │ │ ├── WithdrawForm.tsx
│ │ │ ├── WithdrawReview.tsx
│ │ │ └── interfaces.ts
│ │ ├── TransferModal.tsx
│ │ ├── UsersList.tsx
│ │ ├── VerifyLoader.tsx
│ │ ├── VerifyingMessage.tsx
│ │ ├── WalletLoader.tsx
│ │ ├── admin
│ │ │ └── NewAdmin.tsx
│ │ ├── datetime-picker
│ │ │ └── index.tsx
│ │ └── select
│ │ │ └── index.tsx
│ ├── contexts
│ │ ├── app.ts
│ │ └── appInitialState.ts
│ ├── i18n.ts
│ ├── index.tsx
│ ├── interfaces
│ │ ├── account.ts
│ │ ├── approval.ts
│ │ ├── blockchain.ts
│ │ ├── cico.ts
│ │ ├── currencies.ts
│ │ ├── payment_details.ts
│ │ ├── settings.ts
│ │ ├── settlement.ts
│ │ ├── system.ts
│ │ ├── transaction.ts
│ │ └── user.ts
│ ├── locales
│ │ ├── en
│ │ │ ├── admin.json
│ │ │ ├── auth.json
│ │ │ ├── funds_pull_pre_approval.json
│ │ │ ├── index.ts
│ │ │ ├── layout.json
│ │ │ ├── legal.json
│ │ │ ├── payment.json
│ │ │ ├── receive.json
│ │ │ ├── send.json
│ │ │ ├── settings.json
│ │ │ ├── transaction.json
│ │ │ ├── transfer.json
│ │ │ ├── validations.json
│ │ │ └── verify.json
│ │ ├── es
│ │ │ ├── admin.json
│ │ │ ├── auth.json
│ │ │ ├── funds_pull_pre_approval.json
│ │ │ ├── index.ts
│ │ │ ├── layout.json
│ │ │ ├── payment.json
│ │ │ ├── receive.json
│ │ │ ├── send.json
│ │ │ ├── settings.json
│ │ │ ├── transaction.json
│ │ │ ├── transfer.json
│ │ │ ├── validations.json
│ │ │ └── verify.json
│ │ └── index.ts
│ ├── pages
│ │ ├── Account.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── FundsPullPreApprovals.tsx
│ │ ├── Home.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── Settings.tsx
│ │ ├── Signin.tsx
│ │ ├── Signup.tsx
│ │ ├── Transactions.tsx
│ │ ├── Verify.tsx
│ │ ├── VerifySteps
│ │ │ ├── Step1Identity.tsx
│ │ │ ├── Step2Country.tsx
│ │ │ ├── Step3Address.tsx
│ │ │ ├── Step4Document.tsx
│ │ │ ├── Step5DefaultCurrency.tsx
│ │ │ └── interfaces.ts
│ │ └── admin
│ │ │ ├── Admins.tsx
│ │ │ ├── Home.tsx
│ │ │ ├── Liquidity.tsx
│ │ │ └── Users.tsx
│ ├── react-app-env.d.ts
│ ├── services
│ │ ├── backendClient.test.ts
│ │ ├── backendClient.ts
│ │ ├── errors.ts
│ │ └── sessionStorage.ts
│ ├── tests
│ │ └── stubs.ts
│ └── utils
│ │ ├── amount-precision.ts
│ │ ├── amountPrecision.test.ts
│ │ ├── auth-routes.tsx
│ │ ├── class-names.ts
│ │ ├── dropdown-options.ts
│ │ ├── payment-params.ts
│ │ └── paymentParams.test.ts
├── tsconfig.json
└── yarn.lock
├── gateway
├── Dockerfile
├── nginx.conf
├── nginx.debug.conf
├── nginx.dev.conf
└── nginx.static.conf
├── helm
└── reference-wallet
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── backend-deployment.yaml
│ ├── backend-service.yaml
│ ├── frontend-deployment.yaml
│ ├── frontend-service.yaml
│ ├── ingress.yaml
│ ├── peripherals-deployment.yaml
│ ├── peripherals-service.yaml
│ ├── serviceaccount.yaml
│ └── volumes.yaml
│ └── values.yaml
├── mobile
├── .buckconfig
├── .dockerignore
├── .env.example
├── .eslintrc.js
├── .gitattributes
├── .gitignore
├── .prettierrc.js
├── .watchmanconfig
├── README.md
├── __tests__
│ └── App-test.tsx
├── android
│ ├── Dockerfile
│ ├── Gemfile
│ ├── Gemfile.lock
│ ├── app
│ │ ├── _BUCK
│ │ ├── build.gradle
│ │ ├── build_defs.bzl
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── lrw
│ │ │ │ └── ReactNativeFlipper.java
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets
│ │ │ └── fonts
│ │ │ │ ├── AntDesign.ttf
│ │ │ │ ├── Entypo.ttf
│ │ │ │ ├── EvilIcons.ttf
│ │ │ │ ├── Feather.ttf
│ │ │ │ ├── FontAwesome.ttf
│ │ │ │ ├── FontAwesome5_Brands.ttf
│ │ │ │ ├── FontAwesome5_Regular.ttf
│ │ │ │ ├── FontAwesome5_Solid.ttf
│ │ │ │ ├── Fontisto.ttf
│ │ │ │ ├── Foundation.ttf
│ │ │ │ ├── FreeSans-Bold.ttf
│ │ │ │ ├── FreeSans-Regular.ttf
│ │ │ │ ├── Ionicons.ttf
│ │ │ │ ├── MaterialCommunityIcons.ttf
│ │ │ │ ├── MaterialIcons.ttf
│ │ │ │ ├── Octicons.ttf
│ │ │ │ ├── SimpleLineIcons.ttf
│ │ │ │ └── Zocial.ttf
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── lrw
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MainApplication.java
│ │ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── fastlane
│ │ ├── Appfile
│ │ ├── Fastfile
│ │ └── README.md
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── publish.sh
│ └── settings.gradle
├── app.json
├── babel.config.js
├── index.js
├── ios
│ ├── Gemfile
│ ├── LRW.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── LRW-tvOS.xcscheme
│ │ │ └── LRW.xcscheme
│ ├── LRW.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── LRW
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.xib
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── 1024.png
│ │ │ │ ├── 120-1.png
│ │ │ │ ├── 120.png
│ │ │ │ ├── 180.png
│ │ │ │ ├── 40.png
│ │ │ │ ├── 58.png
│ │ │ │ ├── 60.png
│ │ │ │ ├── 80.png
│ │ │ │ ├── 87.png
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── icons
│ │ │ ├── 1024.png
│ │ │ ├── 120.png
│ │ │ ├── 180.png
│ │ │ ├── 40.png
│ │ │ ├── 58.png
│ │ │ ├── 60.png
│ │ │ ├── 80.png
│ │ │ └── 87.png
│ │ └── main.m
│ ├── Podfile
│ ├── Podfile.lock
│ ├── fastlane
│ │ ├── Appfile
│ │ ├── Fastfile
│ │ ├── Matchfile
│ │ └── README.md
│ └── publish.sh
├── metro.config.js
├── package.json
├── react-native.config.js
├── src
│ ├── assets
│ │ ├── back-arrow.svg
│ │ ├── chevron.svg
│ │ ├── fonts
│ │ │ └── freesans
│ │ │ │ ├── FreeSans-Bold.ttf
│ │ │ │ └── FreeSans-Regular.ttf
│ │ ├── gears.svg
│ │ ├── logo.png
│ │ ├── logo.svg
│ │ └── scan-qr.svg
│ ├── components
│ │ ├── AppHeader.tsx
│ │ ├── BalancesList.tsx
│ │ ├── CurrencyBalance.tsx
│ │ ├── DatePicker.tsx
│ │ ├── ExampleSectionWarning.tsx
│ │ ├── ExplorerLink.tsx
│ │ ├── InputErrorMessage.tsx
│ │ ├── LegalDisclaimer.tsx
│ │ ├── Messages
│ │ │ ├── ErrorMessage.tsx
│ │ │ └── InfoMessage.tsx
│ │ ├── NetworkIndicator.tsx
│ │ ├── PaymentMethodsForm.tsx
│ │ ├── PreferencesForm.tsx
│ │ ├── ScreenLayout.tsx
│ │ ├── Select.tsx
│ │ ├── TestnetWarning.tsx
│ │ ├── TotalBalance.tsx
│ │ ├── TransactionsList.tsx
│ │ └── VerifyingMessage.tsx
│ ├── contexts
│ │ ├── account.tsx
│ │ ├── rates.tsx
│ │ └── user.tsx
│ ├── currencies.ts
│ ├── i18n.ts
│ ├── interfaces
│ │ ├── account.ts
│ │ ├── blockchain.ts
│ │ ├── cico.ts
│ │ ├── currencies.ts
│ │ ├── transaction.ts
│ │ └── user.ts
│ ├── locales
│ │ ├── en
│ │ │ ├── auth.json
│ │ │ ├── index.ts
│ │ │ ├── layout.json
│ │ │ ├── legal.json
│ │ │ ├── receive.json
│ │ │ ├── send.json
│ │ │ ├── settings.json
│ │ │ ├── transaction.json
│ │ │ ├── transfer.json
│ │ │ ├── validations.json
│ │ │ └── verify.json
│ │ ├── es
│ │ │ ├── auth.json
│ │ │ ├── index.ts
│ │ │ ├── layout.json
│ │ │ ├── receive.json
│ │ │ ├── send.json
│ │ │ ├── settings.json
│ │ │ ├── transaction.json
│ │ │ ├── transfer.json
│ │ │ ├── validations.json
│ │ │ └── verify.json
│ │ └── index.ts
│ ├── screens
│ │ ├── Account.tsx
│ │ ├── AddBankAccount.tsx
│ │ ├── AddCreditCard.tsx
│ │ ├── ConnectionError.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── Home.tsx
│ │ ├── Receive.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── Send
│ │ │ ├── Send.tsx
│ │ │ ├── SendReview.tsx
│ │ │ └── SendScanQR.tsx
│ │ ├── Settings.tsx
│ │ ├── SignIn.tsx
│ │ ├── SignUp.tsx
│ │ ├── SingleTransaction.tsx
│ │ ├── Transactions.tsx
│ │ ├── Transfer.tsx
│ │ ├── Transfer
│ │ │ ├── Convert.tsx
│ │ │ ├── ConvertReview.tsx
│ │ │ ├── Deposit.tsx
│ │ │ ├── DepositReview.tsx
│ │ │ ├── Withdraw.tsx
│ │ │ └── WithdrawReview.tsx
│ │ ├── Verify.tsx
│ │ └── VerifySteps
│ │ │ ├── Step1Identity.tsx
│ │ │ ├── Step2Country.tsx
│ │ │ ├── Step3Address.tsx
│ │ │ ├── Step4Document.tsx
│ │ │ ├── Step5DefaultCurrency.tsx
│ │ │ └── interfaces.ts
│ ├── services
│ │ ├── backendClient.ts
│ │ ├── errors.ts
│ │ └── sessionStorage.ts
│ ├── styles.ts
│ └── utils
│ │ ├── amount-precision.ts
│ │ ├── amountPrecision.test.ts
│ │ ├── dropdown-options.ts
│ │ └── shorten-address.ts
├── tsconfig.json
└── yarn.lock
├── scripts
├── README.md
├── compile_frontend.sh
├── funcs.sh
├── generate_i18n.py
├── install-git-hooks.sh
├── lrw.sh
├── pre-commit
├── run_dmw_test.sh
├── set_copyright_headers.py
├── set_env.py
└── wait_for_server_ready.sh
├── vasp-validator
├── .env.example
├── .flake8
├── Pipfile
├── Pipfile.lock
├── README.md
├── lint.sh
├── pytest.ini
├── setup.py
├── src
│ └── vasp_validator
│ │ ├── __init__.py
│ │ ├── models.py
│ │ ├── models_fppa.py
│ │ ├── reference_wallet_proxy.py
│ │ ├── tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── plugin.py
│ │ ├── test_charge_payment_command.py
│ │ ├── test_funds_pull_preapproval.py
│ │ ├── test_p2m.py
│ │ ├── test_tx_no_travel_rule.py
│ │ ├── test_tx_with_travel_rule_success.py
│ │ └── vasp_proxy_hook.py
│ │ ├── validator_client.py
│ │ └── vasp_proxy.py
├── test.sh
└── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_vasp_proxy_hook.py
│ └── vasp_proxy_testee.py
└── wait.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | # All the hidden files and directories
2 | **/.*
3 |
4 | # Not needed for the backend
5 | docker
6 | frontend
7 | gateway
8 | scripts
9 | helm/
10 |
11 | requirements.txt
12 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # Env file for docker-compose proejct name.
2 |
3 | COMPOSE_PROJECT_NAME=lrw
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B \U0001F5C4 Backend Bug report"
3 | about: Create a bug report to help improve the Diem Reference Wallet Backend
4 | title: "[Bug]"
5 | labels: bug, backend
6 | assignees: ''
7 |
8 | ---
9 |
10 | # 🐛 Bug
11 |
12 | If you're looking to report an issue with the Diem Core project go to https://github.com/libra/libra
13 |
14 |
17 |
18 | ## Steps to reproduce
19 |
20 |
21 |
22 | ** Error message or problem **
23 | ```
24 | // Paste the output here
25 | ```
26 |
27 | ## Expected Behavior
28 |
29 |
30 |
31 | ## System information
32 |
33 | **Please complete the following information:**
34 | -
35 |
36 |
37 | ## Additional context
38 |
39 |
40 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report_mobile.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B \U0001F4F1 Mobile App Bug report"
3 | about: Create a bug report to help improve the Diem Reference Wallet Mobile App
4 | title: "[Bug]"
5 | labels: bug, mobile
6 | assignees: ''
7 |
8 | ---
9 |
10 | # 🐛 Bug
11 |
12 | If you're looking to report an issue with the Diem Core project go to https://github.com/libra/libra
13 |
14 |
17 |
18 | ## Steps to reproduce
19 |
20 |
21 |
22 | ** Error message or problem **
23 | ```
24 | // Paste the output here
25 | ```
26 |
27 | ## Expected Behavior
28 |
29 |
30 |
31 | ## System information
32 |
33 | **Please complete the following information:**
34 | -
35 | -
36 |
37 |
38 | ## Additional context
39 |
40 |
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report_web.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B \U0001F4BB Web Client Bug report"
3 | about: Create a bug report to help improve the Diem Reference Web Client
4 | title: "[Bug]"
5 | labels: bug, web
6 | assignees: ''
7 |
8 | ---
9 |
10 | # 🐛 Bug
11 |
12 | If you're looking to report an issue with the Diem Core project go to https://github.com/libra/libra
13 |
14 |
17 |
18 | ## Steps to reproduce
19 |
20 |
21 |
22 | ** Error message or problem **
23 | ```
24 | // Paste the output here
25 | ```
26 |
27 | ## Expected Behavior
28 |
29 |
30 |
31 | ## System information
32 |
33 | **Please complete the following information:**
34 | -
35 | -
36 |
37 |
38 | ## Additional context
39 |
40 |
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/new-feature.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U00002728 New Feature Request"
3 | about: Suggest a new feature for Reference Wallet
4 | title: "[feature-request]"
5 | labels: feature-request
6 | assignees: ''
7 |
8 | ---
9 |
10 | # New Feature Request Description
11 |
12 |
13 |
14 | ## Why would this be useful?
15 |
16 |
17 |
18 | ## Additional context
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | ## Motivation
6 |
7 | (Write your motivation for proposed changes here.)
8 |
9 | ### Have you read the [Contributing Guidelines on pull requests](https://github.com/libra/libra-wallet/blob/master/CONTRIBUTING.md#pull-requests)?
10 |
11 | (Write your answer here.)
12 |
13 | ## Test Plan
14 |
15 | (Share your test plan here. If you changed code, please provide us with clear instructions for verifying that your changes work.)
16 |
17 | ## Related PRs
18 |
19 | (If your PR adds or changes functionality, please take time to update the docs at https://github.com/libra/website, and link to your PR here.)
20 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | - develop
8 | push:
9 | branches:
10 | - master
11 | - develop
12 |
13 | jobs:
14 | build:
15 |
16 | runs-on: ubuntu-latest
17 | strategy:
18 | matrix:
19 | python-version: [3.7]
20 |
21 | steps:
22 | - uses: actions/checkout@v2
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v1
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 | - name: Install pipenv
28 | run: |
29 | pip install --upgrade pipenv
30 | - name: Fetch liquidity submodule
31 | run: |
32 | git submodule update --init --recursive
33 | - name: Install dependencies for backend
34 | run: |
35 | cd backend && pipenv install --dev
36 | cd ../liquidity && pipenv install --dev
37 | cd ..
38 | - name: Setup env
39 | run: |
40 | ./scripts/lrw.sh setup_environment
41 | - name: Test with pytest
42 | run: |
43 | ./scripts/lrw.sh watch_test
44 | - name: Compile frontend
45 | run: |
46 | ./scripts/compile_frontend.sh
47 |
--------------------------------------------------------------------------------
/.github/workflows/dmw_test.yaml:
--------------------------------------------------------------------------------
1 | name: DMW Test
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | - develop
8 | push:
9 | branches:
10 | - master
11 | - develop
12 |
13 | jobs:
14 | build:
15 |
16 | runs-on: ubuntu-latest
17 | strategy:
18 | matrix:
19 | python-version: [3.7]
20 |
21 | steps:
22 | - uses: actions/checkout@v2
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v1
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 | - name: Install pipenv
28 | run: pip install --upgrade pipenv
29 | - name: Fetch liquidity submodule
30 | run: git submodule update --init --recursive
31 | - name: Setup Environment
32 | run: |
33 | VASP_BASE_URL=http://localhost:8080 ./scripts/lrw.sh setup_environment false
34 | - name: Launch tests against it
35 | run: ./scripts/run_dmw_test.sh
36 | - name: Save results
37 | uses: actions/upload-artifact@v2
38 | if: ${{ always() }}
39 | with:
40 | name: test-output
41 | path: |
42 | output
43 |
--------------------------------------------------------------------------------
/.github/workflows/e2e.yaml:
--------------------------------------------------------------------------------
1 | name: E2E Test
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | - develop
8 | push:
9 | branches:
10 | - master
11 | - develop
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | strategy:
17 | matrix:
18 | python-version: [3.7]
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 | - name: Set up Python ${{ matrix.python-version }}
23 | uses: actions/setup-python@v1
24 | with:
25 | python-version: ${{ matrix.python-version }}
26 | - name: Check kill switch
27 | id: check_ks
28 | run: |
29 | if [ -z "${{ secrets.KILL_SWITCH_E2E_TEST }}" ]; then
30 | echo "::set-output name=should_run::false";
31 | else
32 | echo "::set-output name=should_run::true";
33 | fi;
34 | - name: Install pipenv
35 | run: |
36 | pip install --upgrade pipenv
37 | - name: run e2e tests
38 | if: steps.check_ks.outputs.should_run == 'true'
39 | run: |
40 | make setup-env e2e
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | venv/
2 | .idea/
3 | /**/__pycache__
4 | /.pyre
5 | /.eggs
6 | dump.rdb
7 | *.egg-info
8 | *flask_session
9 | **/.DS_Store
10 | e2e.vars
11 | single.vars
12 | double.vars
13 | build
14 | # Frontend build artifacts
15 | /gateway/tmp
16 |
17 | # pyenv local version
18 | .python-version
19 |
20 | */fastlane/report.xml
21 | */fastlane/Preview.html
22 | */fastlane/screenshots
23 |
24 | # dotenv
25 | .env*
26 | !.env.example
27 |
28 | # Bundle artifact
29 | *.jsbundle
30 |
31 | # CocoaPods
32 | /ios/Pods/
33 |
34 | backend/.eggs/
35 | backend/pyproject.toml
36 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "liquidity"]
2 | path = liquidity
3 | url = https://github.com/diem/liquidity-emulator.git
4 |
--------------------------------------------------------------------------------
/.pyre_configuration:
--------------------------------------------------------------------------------
1 | {
2 | "source_directories": [
3 | "backend/"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | The project has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://developers.libra.org/docs/policies/code-of-conduct) so that you can understand what actions will and will not be tolerated.
4 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to pubsub-proxy
2 |
3 | This project welcomes contributions.
4 |
5 | ## Contributor License Agreement
6 |
7 | For pull request to be accepted by any Diem projects, a CLA must be signed.
8 | You will only need to do this once to work on any of Diem's open source
9 | projects.
10 |
11 | When submitting a PR, the diem-github-bot will check your comment for a valid CLA. If one is not found, then you will need to submit an Individual CLA for yourself or a Corporate CLA for your company.
12 |
13 | ## Submitting Issues and Feature Requests
14 |
15 | The Diem Reference Wallet uses [GitHub issues](https://github.com/diem/reference-wallet/issues) to track bugs and feature requests. Please include necessary information and instructions to reproduce your issue or describe your use case.
16 |
17 | ## Other Ways to Provide Feedback
18 |
19 | You can also submit product or design feedback while on the demo web and mobile wallet by selecting [Feedback].
20 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policies and Procedures
2 |
3 | Please see Diem's
4 | [security policies](https://developers.libra.org/docs/policies/security) and
5 | procedures for reporting vulnerabilities.
6 |
--------------------------------------------------------------------------------
/backend/.env.example:
--------------------------------------------------------------------------------
1 | GW_PORT=8080
2 | WALLET_CUSTODY_ACCOUNT_NAME=wallet
3 | CUSTODY_PRIVATE_KEYS={"${WALLET_CUSTODY_ACCOUNT_NAME}":""}
4 | VASP_ADDR=
5 | LIQUIDITY_SERVICE_HOST=liquidity
6 | LIQUIDITY_SERVICE_PORT=5000
7 |
--------------------------------------------------------------------------------
/backend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7-slim
2 |
3 | WORKDIR /wallet
4 |
5 | RUN apt-get update && apt-get install -y gcc git
6 | RUN apt-get install -y curl netcat
7 | RUN pip install pipenv
8 |
9 | COPY wait.sh /
10 | COPY backend/ .
11 |
12 | RUN pipenv install --deploy --system
13 |
--------------------------------------------------------------------------------
/backend/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include src *.html
2 |
3 |
--------------------------------------------------------------------------------
/backend/context/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import typing
5 | from .context import from_config, from_env, for_local_dev, generate, Context
6 |
7 |
8 | # a global variable for storing shared instance, use get / set to access
9 | _context: typing.Optional[Context] = None
10 |
11 |
12 | def set(ctx: typing.Optional[Context]) -> None:
13 | global _context
14 | _context = ctx
15 |
16 |
17 | def get() -> Context:
18 | global _context
19 | if _context is None:
20 | raise ValueError("global context is not initialized")
21 | return typing.cast(Context, _context)
22 |
--------------------------------------------------------------------------------
/backend/context/stubs/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from . import custody
5 |
--------------------------------------------------------------------------------
/backend/diem_utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from ._version import get_versions
5 |
6 | __version__ = get_versions()["version"]
7 | del get_versions
8 |
--------------------------------------------------------------------------------
/backend/diem_utils/sdks/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/currencies.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import typing
5 | from enum import Enum
6 |
7 |
8 | class DiemCurrency(str, Enum):
9 | XUS = "XUS"
10 |
11 |
12 | class FiatCurrency(str, Enum):
13 | USD = "USD"
14 | EUR = "EUR"
15 | GBP = "GBP"
16 | CHF = "CHF"
17 | CAD = "CAD"
18 | AUD = "AUD"
19 | NZD = "NZD"
20 | JPY = "JPY"
21 |
22 |
23 | Currencies = typing.Union[FiatCurrency, DiemCurrency]
24 |
25 | DEFAULT_DIEM_CURRENCY = DiemCurrency.XUS.value
26 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/errors.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | class TradeError(Exception):
6 | pass
7 |
8 |
9 | class AlreadySettled(Exception):
10 | pass
11 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/lp.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from dataclasses import dataclass
5 | from typing import Type
6 |
7 | from dataclasses_json import dataclass_json
8 |
9 | from .currency import CurrencyPairs
10 |
11 |
12 | @dataclass_json
13 | @dataclass
14 | class LPDetails:
15 | sub_address: str
16 | vasp: str
17 | IBAN_number: str
18 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/quote.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from dataclasses import dataclass
5 | from datetime import datetime
6 | from typing import NewType
7 | from uuid import UUID
8 |
9 | from dataclasses_json import dataclass_json
10 |
11 | from .currency import CurrencyPair
12 |
13 | QuoteId = NewType("QuoteId", UUID)
14 |
15 |
16 | @dataclass_json
17 | @dataclass
18 | class Rate:
19 | pair: CurrencyPair
20 | rate: int
21 |
22 |
23 | @dataclass_json
24 | @dataclass
25 | class QuoteData:
26 | quote_id: QuoteId
27 | rate: Rate
28 | expires_at: datetime
29 | amount: int
30 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/settlement.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import uuid
5 | from dataclasses import dataclass
6 | from enum import Enum
7 | from typing import NewType
8 |
9 | from dataclasses_json import dataclass_json
10 |
11 | from .currency import Currency
12 |
13 | DebtId = NewType("DebtId", uuid.UUID)
14 |
15 |
16 | @dataclass_json
17 | @dataclass
18 | class DebtData:
19 | debt_id: DebtId
20 | currency: Currency
21 | amount: int # Positive value - Wallet owes LP, negative value - LP owes Wallet
22 |
--------------------------------------------------------------------------------
/backend/diem_utils/types/liquidity/trade.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from dataclasses import dataclass
5 | from enum import Enum
6 | from typing import NewType, Optional
7 | from uuid import UUID
8 |
9 | from dataclasses_json import dataclass_json
10 |
11 | from .currency import CurrencyPair
12 | from .quote import QuoteData
13 |
14 |
15 | class Direction(str, Enum):
16 | Buy = "Buy"
17 | Sell = "Sell"
18 |
19 |
20 | TradeId = NewType("TradeId", UUID)
21 |
22 |
23 | @dataclass_json
24 | @dataclass
25 | class AddressSequence:
26 | address: str
27 | sequence: int
28 |
29 |
30 | class TradeStatus(str, Enum):
31 | Pending = "Pending"
32 | Complete = "Complete"
33 | Consolidated = "Consolidated"
34 |
35 |
36 | @dataclass_json
37 | @dataclass
38 | class TradeData:
39 | trade_id: TradeId
40 | direction: Direction
41 | pair: CurrencyPair
42 | amount: float
43 | status: TradeStatus
44 | quote: QuoteData
45 | tx_version: Optional[int] = None
46 |
--------------------------------------------------------------------------------
/backend/offchain/action.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | from enum import Enum
6 |
7 |
8 | class Action(Enum):
9 | EVALUATE_KYC_DATA = "evaluate_kyc_data"
10 | REVIEW_KYC_DATA = "review_kyc_data"
11 | CLEAR_SOFT_MATCH = "clear_soft_match"
12 | SUBMIT_TXN = "submit_transaction"
13 |
--------------------------------------------------------------------------------
/backend/offchain/command.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from abc import ABC, abstractmethod
5 | from .action import Action
6 | from .types import CommandRequestObject
7 |
8 | import typing
9 |
10 |
11 | class Command(ABC):
12 | @abstractmethod
13 | def id(self) -> str:
14 | """Returns cid of command object"""
15 |
16 | def command_type(self) -> str:
17 | ...
18 |
19 | @abstractmethod
20 | def is_inbound(self) -> bool:
21 | ...
22 |
23 | @abstractmethod
24 | def follow_up_action(self) -> typing.Optional[Action]:
25 | ...
26 |
27 | @abstractmethod
28 | def reference_id(self) -> str:
29 | ...
30 |
31 | @abstractmethod
32 | def new_request(self) -> CommandRequestObject:
33 | ...
34 |
35 | @abstractmethod
36 | def validate(self, prior: typing.Optional["Command"]) -> None:
37 | ...
38 |
39 | @abstractmethod
40 | def my_address(self) -> str:
41 | """Returns my account identifier used for sending command request"""
42 | ...
43 |
44 | @abstractmethod
45 | def counterparty_address(self) -> str:
46 | """Returns the counterparty account identifier that receives the command request"""
47 | ...
48 |
--------------------------------------------------------------------------------
/backend/offchain/error.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from .types import (
5 | OffChainErrorType,
6 | OffChainErrorObject,
7 | )
8 |
9 | import typing
10 |
11 |
12 | class Error(Exception):
13 | obj: OffChainErrorObject
14 |
15 | def __init__(self, obj: OffChainErrorObject) -> None:
16 | super(Exception, self).__init__(obj)
17 | self.obj = obj
18 |
19 |
20 | def command_error(code: str, message: str, field: typing.Optional[str] = None) -> Error:
21 | return Error(
22 | obj=OffChainErrorObject(
23 | type=OffChainErrorType.command_error,
24 | code=code,
25 | field=field,
26 | message=message,
27 | )
28 | )
29 |
30 |
31 | def protocol_error(
32 | code: str, message: str, field: typing.Optional[str] = None
33 | ) -> Error:
34 | return Error(
35 | obj=OffChainErrorObject(
36 | type=OffChainErrorType.protocol_error,
37 | code=code,
38 | field=field,
39 | message=message,
40 | )
41 | )
42 |
--------------------------------------------------------------------------------
/backend/offchain/funds_pull_pre_approval_command_state.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import typing
5 |
6 | from .types import FundPullPreApprovalStatus
7 |
8 | Status = str
9 |
10 | _transitions: typing.Dict[Status, typing.List[Status]] = {
11 | FundPullPreApprovalStatus.pending: [
12 | FundPullPreApprovalStatus.pending,
13 | FundPullPreApprovalStatus.valid,
14 | FundPullPreApprovalStatus.rejected,
15 | FundPullPreApprovalStatus.closed,
16 | ],
17 | FundPullPreApprovalStatus.valid: [
18 | FundPullPreApprovalStatus.valid,
19 | FundPullPreApprovalStatus.closed,
20 | ],
21 | FundPullPreApprovalStatus.rejected: [
22 | FundPullPreApprovalStatus.rejected,
23 | ],
24 | FundPullPreApprovalStatus.closed: [
25 | FundPullPreApprovalStatus.closed,
26 | ],
27 | }
28 |
29 | _initial_states: typing.List[Status] = [
30 | FundPullPreApprovalStatus.pending,
31 | FundPullPreApprovalStatus.valid,
32 | FundPullPreApprovalStatus.rejected,
33 | ]
34 |
35 |
36 | def is_valid_transition(current_status: Status, next_status: Status) -> bool:
37 | return next_status in _transitions[current_status]
38 |
39 |
40 | def is_valid_initial_status(status: Status) -> bool:
41 | return status in _initial_states
42 |
--------------------------------------------------------------------------------
/backend/offchain/http_header.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | X_REQUEST_ID: str = "X-REQUEST-ID"
5 | X_REQUEST_SENDER_ADDRESS: str = "X-REQUEST-SENDER-ADDRESS"
6 |
--------------------------------------------------------------------------------
/backend/offchain/types/cid.py:
--------------------------------------------------------------------------------
1 | import uuid
2 |
3 |
4 | def generate_cid() -> str:
5 | return str(uuid.uuid4())
6 |
--------------------------------------------------------------------------------
/backend/pubsub/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import os
5 |
6 | VASP_ADDR = os.getenv("VASP_ADDR")
7 | JSON_RPC_URL = os.getenv("JSON_RPC_URL")
8 |
9 | DEFL_CONFIG = {
10 | "diem_node_uri": JSON_RPC_URL,
11 | "sync_interval_ms": 1000,
12 | "progress_file_path": "/tmp/pubsub_progress",
13 | "accounts": [VASP_ADDR],
14 | }
15 |
--------------------------------------------------------------------------------
/backend/pubsub/__main__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import argparse
5 | import json
6 | import sys
7 |
8 | from pubsub import DEFL_CONFIG, VASP_ADDR
9 | from pubsub.client import LRWPubSubClient
10 |
11 |
12 | parser = argparse.ArgumentParser(
13 | description="Pubsub CLI tool. Takes in pubsub config file or VASP_ADDR environment variable"
14 | )
15 | parser.add_argument("-f", "--file", type=str, help="LRW pubsub config file path")
16 | args = parser.parse_args()
17 |
18 | if args.file:
19 | try:
20 | with open(args.file) as f:
21 | conf = json.load(f)
22 | except:
23 | print("Missing or invalid config file, exiting...")
24 | sys.exit(1)
25 | else: # load in by env var
26 | if not VASP_ADDR:
27 | print("Missing VASP_ADDR environment variable, exiting...")
28 | sys.exit(1)
29 | conf = DEFL_CONFIG
30 |
31 | print(conf)
32 |
33 | client = LRWPubSubClient(conf)
34 | client.start()
35 |
--------------------------------------------------------------------------------
/backend/run_pubsub.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | python3 -m pubsub
7 |
--------------------------------------------------------------------------------
/backend/run_web.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | export FLASK_ENV=${COMPOSE_ENV:-development}
7 | export FLASK_APP="webapp:init()"
8 |
9 | pipenv run flask run --host 0.0.0.0 --port ${WALLET_PORT:-5000} --no-reload
10 |
--------------------------------------------------------------------------------
/backend/run_worker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | PROCS=${PROCS:-2}
7 | THREADS=${THREADS:-2}
8 |
9 | if [ -z "${PROCS##*[!0-9]*}" ] || [ -z "${THREADS##*[!0-9]*}" ]; then
10 | echo "PROCS and THREADS env vars should be integers"
11 | exit 1
12 | fi
13 |
14 | dramatiq wallet -p $PROCS -t $THREADS --verbose --watch . "$@"
15 |
--------------------------------------------------------------------------------
/backend/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from setuptools import setup, find_packages
5 |
6 | setup(
7 | name="diem-sample-wallet",
8 | version="0.1.0",
9 | description="Sample custodial wallet implementation",
10 | python_requires=">=3.5",
11 | packages=find_packages(),
12 | tests_require=["pytest", "pytest-runner"],
13 | package_dir={"": "."},
14 | setup_requires=["pytest-runner"],
15 | )
16 |
--------------------------------------------------------------------------------
/backend/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -xv
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
7 |
8 | set -euo pipefail
9 |
10 | # pipenv run black --check $DIR
11 |
12 | # NOTE:
13 | # each of these test modules need to be run independently due to how they
14 | # instantiate dramatiq and other test dependencies in conftest.py
15 | pipenv run python3 $DIR/setup.py pytest --addopts="$DIR/tests/wallet_tests $@"
16 | pipenv run python3 $DIR/setup.py pytest --addopts="$DIR/tests/webapp_tests $@"
17 | pipenv run python3 $DIR/setup.py pytest --addopts="$DIR/tests/pubsub_tests $@"
18 | pipenv run python3 $DIR/setup.py pytest --addopts="$DIR/tests/context_tests $@"
19 |
--------------------------------------------------------------------------------
/backend/tests/README.md:
--------------------------------------------------------------------------------
1 | # tests
2 |
3 | Tests exist in a separate package because of dramatiq broker instantiation when one does `import wallet` for the first time
4 |
--------------------------------------------------------------------------------
/backend/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/e2e_tests/double/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/e2e_tests/single/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/e2e_tests/single/test_init.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import json
5 | import random
6 |
7 | import requests
8 | from tests.e2e_tests import LRW_WEB_1
9 |
10 |
11 | def test_init() -> None:
12 | # just test that the webapp works
13 | res = requests.get(f"{LRW_WEB_1}/api/execution_logs")
14 | assert res.ok
15 |
16 |
17 | def test_create_account() -> None:
18 | num = random.randint(0, 1000)
19 | payload = {"username": f"fakeuser{num}", "password": "fakepassword"}
20 | res = requests.post(f"{LRW_WEB_1}/api/user", json=payload)
21 | assert res.ok
22 | token = res.text.strip('"')
23 | headers = {"Authorization": f"Bearer {token}"}
24 | users_res = requests.get(f"{LRW_WEB_1}/api/user", headers=headers)
25 | assert users_res.ok
26 | user = json.loads(users_res.text)
27 | assert user.get("username") == payload.get("username")
28 |
--------------------------------------------------------------------------------
/backend/tests/mw_drw_proxy/README.md:
--------------------------------------------------------------------------------
1 | # MiniWallet <=> Reference Wallet Proxy
2 |
3 | This will run a proxy which allows the DMW test suite to communicate with DRW.
4 |
5 | For example, when the DRW requests to set up a user, the proxy registers a user, updates their information with KYC,
6 | and deposits any initial test balances that the DMW required, before returning an identifier for that user which DMW
7 | will reuse in future calls.
8 |
9 |
10 | ### Usage:
11 | (from inside the venv)
12 | ```
13 | DRW_URL_PREFIX=http://reference_wallet:8080 MW_DRW_PROXY_PORT=3130 pipenv run python3 tests/mw_drw_proxy/proxy.py
14 | ```
15 | This will launch the proxy server on `http://localhost:3130`, and will proxy the requests to an instance of
16 | DRW running at `http://reference_wallet:8080`
--------------------------------------------------------------------------------
/backend/tests/mw_drw_proxy/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/offchain_tests/test_deserialize.py:
--------------------------------------------------------------------------------
1 | from diem import LocalAccount
2 | from offchain import CommandResponseObject, jws, CommandResponseStatus
3 |
4 |
5 | def test_serialize_deserialize():
6 | account = LocalAccount.generate()
7 | response = CommandResponseObject(
8 | status=CommandResponseStatus.success,
9 | cid="3185027f05746f5526683a38fdb5de98",
10 | )
11 | ret = jws.serialize(response, account.private_key.sign)
12 |
13 | resp = jws.deserialize(
14 | ret,
15 | CommandResponseObject,
16 | account.private_key.public_key().verify,
17 | )
18 | assert resp == response
19 |
--------------------------------------------------------------------------------
/backend/tests/pubsub_tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | ASSOC_ADDRESS: str = "0000000000000000000000000a550c18"
5 | ASSOC_AUTHKEY: str = "3126dc954143b1282565e8829cd8cdfdc179db444f64b406dee28015fce7f392"
6 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/liquidity/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/liquidity/client/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/liquidity/client/test_client.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # import pytest
5 | #
6 | # from diem_utils.types.liquidity.currency import CurrencyPair, Currency
7 | # from liquidity.fx import fixed_rates
8 | # from wallet.lp_client import LpClient
9 | #
10 | #
11 | # def test_get_quote_for_supported_currency_pair(liquidity_provider_session):
12 | # pair = CurrencyPair(Currency.XUS, Currency.USD)
13 | # quote = LpClient().get_quote(pair, 1)
14 | #
15 | # assert quote.rate.rate == fixed_rates[str(pair)]
16 | # assert quote.rate.pair == pair
17 | #
18 | #
19 | # def test_get_quote_unsupported_currency_pair(liquidity_provider_session):
20 | # with pytest.raises(LookupError):
21 | # pair = CurrencyPair(Currency.CHF, Currency.USD)
22 | # LpClient().get_quote(pair, 1)
23 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/liquidity/test_amount.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from diem_utils.precise_amount import Amount
7 |
8 | ONE_DIEM = Amount().deserialize(1000000)
9 | TWO_DIEM = Amount().deserialize(2000000)
10 | TENTH_MILLIDIEM = Amount().deserialize(100)
11 | MAX_PRECISION_DIEM = Amount().deserialize(10000000000000000009)
12 |
13 |
14 | class TestAmount:
15 | def test_mul(self):
16 | x: Amount = ONE_DIEM * ONE_DIEM
17 | assert str(x) == "1.000000"
18 | assert x.serialize() == 1000000
19 |
20 | x: Amount = TENTH_MILLIDIEM * TWO_DIEM
21 | assert str(x) == "0.000200"
22 | assert x.serialize() == 200
23 |
24 | x: Amount = MAX_PRECISION_DIEM * TWO_DIEM
25 | assert str(x) == "20000000000000.000018"
26 | assert x.serialize() == 20000000000000000018
27 |
28 | def test_div(self):
29 | x: Amount = ONE_DIEM / ONE_DIEM
30 | assert str(x) == "1.000000"
31 | assert x.serialize() == 1000000
32 |
33 | x: Amount = ONE_DIEM / TWO_DIEM
34 | assert str(x) == "0.500000"
35 | assert x.serialize() == 500000
36 |
37 | x: Amount = MAX_PRECISION_DIEM / TWO_DIEM
38 | assert str(x) == "5000000000000.000004"
39 | assert x.serialize() == 5000000000000000004
40 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/liquidity/test_utils.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from diem_utils.types.liquidity.currency import CurrencyPairs, CurrencyPair
7 |
8 |
9 | def test_is_not_diem_to_diem():
10 | pair = CurrencyPairs.XUS_USD.value
11 |
12 | assert CurrencyPair.is_diem_to_diem(pair) is False
13 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/seeds/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/seeds/one_approved_user.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from diem_utils.types.currencies import FiatCurrency
7 | from wallet.storage import (
8 | User,
9 | RegistrationStatus,
10 | Account,
11 | )
12 |
13 |
14 | class OneApprovedUser:
15 | username = "test-user"
16 |
17 | @staticmethod
18 | def run(db_session):
19 | user = User(
20 | username=OneApprovedUser.username,
21 | registration_status=RegistrationStatus.Approved,
22 | selected_fiat_currency=FiatCurrency.USD,
23 | selected_language="en",
24 | password_salt="123",
25 | password_hash="deadbeef",
26 | account=Account(name="fake_account_seed"),
27 | )
28 |
29 | db_session.add(user)
30 | db_session.commit()
31 |
32 | return user.id
33 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/seeds/one_p2m_payment_seeder.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | from diem_utils.types.currencies import DiemCurrency
4 | from wallet.services.offchain.p2m_payment import P2MPaymentStatus
5 | from wallet.storage.models import Payment as PaymentModel
6 |
7 |
8 | class OneP2MPaymentSeeder:
9 | @staticmethod
10 | def run(
11 | db_session, vasp_address, reference_id, action="charge", amount=100_000_000
12 | ):
13 | db_session.add(
14 | PaymentModel(
15 | vasp_address=vasp_address,
16 | reference_id=reference_id,
17 | merchant_name="Bond & Gurki Pet Store",
18 | action=action,
19 | currency=DiemCurrency.XUS,
20 | amount=amount,
21 | expiration=datetime(2021, 5, 17),
22 | description="description",
23 | status=P2MPaymentStatus.READY_FOR_USER,
24 | )
25 | )
26 |
27 | db_session.commit()
28 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/seeds/one_user_multiple_transactions.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from copy import deepcopy
7 |
8 | from wallet.storage import Account
9 | from . import prototypes
10 |
11 |
12 | class OneUserMultipleTransactions:
13 | tx1_currency = "XUS"
14 | tx2_currency = "XUS"
15 | total_txs = 2
16 | username = prototypes.username
17 |
18 | @staticmethod
19 | def run(db_session):
20 | user = deepcopy(prototypes.user)
21 | user.account = Account(name="fake_account_seed")
22 | db_session.add(user)
23 | db_session.commit()
24 | db_session.refresh(user)
25 |
26 | tx1 = deepcopy(prototypes.tx)
27 | tx2 = deepcopy(prototypes.tx)
28 |
29 | tx1.source_id = user.account_id
30 | tx1.sequence = 1
31 | tx1.currency = OneUserMultipleTransactions.tx1_currency
32 |
33 | tx2.destination_id = user.account_id
34 | tx2.sequence = tx1.sequence + 1
35 | tx2.currency = OneUserMultipleTransactions.tx2_currency
36 | user.account.sent_transactions.append(tx1)
37 | user.account.received_transactions.append(tx2)
38 |
39 | db_session.add(user)
40 | db_session.add(tx1)
41 | db_session.add(tx2)
42 |
43 | db_session.commit()
44 |
45 | return tx1, tx2, user
46 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/resources/seeds/one_user_with_one_order.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from copy import deepcopy
7 | from . import prototypes
8 |
9 |
10 | class OneUserWithOneOrder:
11 | username = prototypes.username
12 |
13 | @staticmethod
14 | def run(db_session):
15 | user = deepcopy(prototypes.user)
16 | order = deepcopy(prototypes.order)
17 |
18 | user.orders.append(order)
19 |
20 | db_session.add(order)
21 | db_session.add(user)
22 |
23 | db_session.commit()
24 |
25 | return user.id, order.id
26 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/fx/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/fx/test_fx.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | import pytest
7 |
8 | from diem_utils.types.liquidity.currency import CurrencyPairs, Currency
9 | from wallet.services.fx.fx import get_rate
10 |
11 | rates = {
12 | str(CurrencyPairs.XUS_USD.value): 1000000,
13 | str(CurrencyPairs.EUR_XUS.value): 1080000,
14 | str(CurrencyPairs.XUS_JPY.value): 107500000,
15 | str(CurrencyPairs.XUS_CHF.value): 980000,
16 | str(CurrencyPairs.GBP_XUS.value): 1230000,
17 | str(CurrencyPairs.XUS_CAD.value): 1410000,
18 | str(CurrencyPairs.AUD_XUS.value): 640000,
19 | str(CurrencyPairs.NZD_XUS.value): 600000,
20 | }
21 |
22 |
23 | def test_get_rate_direct_conversion_matching_currencies():
24 | rate = get_rate(Currency.XUS, Currency.USD).serialize()
25 |
26 | assert rate == 1000000
27 |
28 |
29 | def test_get_rate_direct_conversion_odd_currencies():
30 | rate = get_rate(Currency.EUR, Currency.XUS).serialize()
31 |
32 | assert rate == 1080000
33 |
34 |
35 | def test_get_rate_non_exist_conversion():
36 | with pytest.raises(LookupError):
37 | get_rate(Currency.CHF, Currency.NZD).serialize()
38 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/system/test_subaddreses_from_metadata.py:
--------------------------------------------------------------------------------
1 | from diem import diem_types, txnmetadata as metadata
2 |
3 | from wallet.services.system import subaddreses_from_metadata
4 |
5 |
6 | def test_general_metadata():
7 | expected_r = bytes.fromhex("1122334455667788")
8 | expected_s = bytes.fromhex("1122334455667789")
9 |
10 | both_set_meta = metadata.general_metadata(expected_s, expected_r).hex()
11 | r, s = subaddreses_from_metadata(both_set_meta)
12 | assert r == expected_r.hex()
13 | assert s == expected_s.hex()
14 |
15 | both_empty_meta = metadata.general_metadata().hex()
16 | r, s = subaddreses_from_metadata(both_empty_meta)
17 | assert r is None
18 | assert s is None
19 |
20 | only_r_meta = metadata.general_metadata(to_subaddress=expected_r).hex()
21 | r, s = subaddreses_from_metadata(only_r_meta)
22 | assert r == expected_r.hex()
23 | assert s is None
24 |
25 | only_s_meta = metadata.general_metadata(from_subaddress=expected_s).hex()
26 | r, s = subaddreses_from_metadata(only_s_meta)
27 | assert r is None
28 | assert s == expected_s.hex()
29 |
30 |
31 | def test_refund_metadata():
32 | meta = metadata.refund_metadata(
33 | original_transaction_version=1,
34 | reason=diem_types.RefundReason__InvalidSubaddress(),
35 | ).hex()
36 | r, s = subaddreses_from_metadata(meta)
37 | assert r is None
38 | assert s is None
39 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/system/test_sync_transaction_method.py:
--------------------------------------------------------------------------------
1 | from tests.wallet_tests.services.system.utils import (
2 | add_incoming_transaction_to_blockchain,
3 | check_number_of_transactions,
4 | )
5 | from tests.wallet_tests.services.system.utils import (
6 | setup_inventory_with_initial_transaction,
7 | )
8 | from wallet.services.account import generate_sub_address
9 | from wallet.services.system import sync_transaction
10 | from wallet.storage import Transaction
11 |
12 | OTHER_ADDRESS_1 = "257e50b131150fdb56aeab4ebe4ec2b9"
13 | SUB_ADDRESS_1 = "8e298f642d08d1af"
14 |
15 |
16 | def test_sync_transaction(patch_blockchain) -> None:
17 | setup_inventory_with_initial_transaction(
18 | patch_blockchain, 1000, mock_blockchain_initial_balance=1000
19 | )
20 |
21 | ADDED_VERSION = 2
22 | transaction = add_incoming_transaction_to_blockchain(
23 | patch_blockchain, generate_sub_address(), 100, OTHER_ADDRESS_1, 2, ADDED_VERSION
24 | )
25 |
26 | check_number_of_transactions(1)
27 |
28 | sync_transaction(transaction)
29 |
30 | check_number_of_transactions(2)
31 |
32 | assert (
33 | Transaction.query.filter_by(blockchain_version=ADDED_VERSION).first()
34 | is not None
35 | )
36 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/services/test_account.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from tests.wallet_tests.resources.seeds.one_user_seeder import OneUser
7 | from wallet.services import account as account_service
8 | from wallet.storage import db_session, User
9 |
10 |
11 | def test_account_viewable_by_same_user():
12 | account_name = "test_account"
13 | user = OneUser.run(db_session, account_name=account_name)
14 |
15 | assert account_service.is_user_allowed_for_account(
16 | account_name=account_name, user=user
17 | )
18 |
19 |
20 | def test_account_not_viewable_by_other_user():
21 | account_name1 = "test_account"
22 | user = OneUser.run(db_session, account_name=account_name1, username="user1")
23 |
24 | account_name2 = "test_account2"
25 | user2 = OneUser.run(db_session, account_name=account_name2, username="user2")
26 |
27 | assert not account_service.is_user_allowed_for_account(
28 | account_name=account_name1, user=user2
29 | )
30 |
31 |
32 | def test_account_viewable_by_admin():
33 | account_name = "test_account"
34 | user = User(id=1, is_admin=True)
35 |
36 | assert account_service.is_user_allowed_for_account(
37 | account_name=account_name, user=user
38 | )
39 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/storage/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/storage/test_fund_pull_pre_approval.py:
--------------------------------------------------------------------------------
1 | from tests.wallet_tests.resources.seeds.one_funds_pull_pre_approval import (
2 | OneFundsPullPreApproval,
3 | )
4 | from wallet.services.offchain.fund_pull_pre_approval_sm import Role
5 | from wallet.storage import (
6 | db_session,
7 | get_command_by_id,
8 | update_command,
9 | )
10 |
11 | FUNDS_PULL_PRE_APPROVAL_ID = "5fc49fa0-5f2a-4faa-b391-ac1652c57e4d"
12 |
13 |
14 | def test_update_at(random_bech32_address, my_user):
15 | OneFundsPullPreApproval.run(
16 | db_session=db_session,
17 | account_id=my_user.account_id,
18 | address=random_bech32_address,
19 | biller_address=my_user.address,
20 | funds_pull_pre_approval_id=FUNDS_PULL_PRE_APPROVAL_ID,
21 | status="pending",
22 | role=Role.PAYEE,
23 | )
24 |
25 | command = get_command_by_id(FUNDS_PULL_PRE_APPROVAL_ID)
26 |
27 | created_at = command.created_at
28 | updated_at = command.updated_at
29 |
30 | command.status = "valid"
31 |
32 | update_command(command)
33 |
34 | updated_command = get_command_by_id(FUNDS_PULL_PRE_APPROVAL_ID)
35 |
36 | assert updated_command.updated_at != updated_at
37 | assert updated_command.updated_at > updated_at
38 | assert updated_command.created_at == created_at
39 | assert updated_command.status == "valid"
40 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/storage/test_order.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from uuid import UUID
7 |
8 | from tests.wallet_tests.resources.seeds.one_user_with_one_order import (
9 | OneUserWithOneOrder,
10 | )
11 | from wallet.storage import db_session, get_order, update_order
12 | from wallet.types import (
13 | OrderStatus,
14 | OrderId,
15 | )
16 |
17 |
18 | def test_get_order(clean_db: None) -> None:
19 | user_id, order_id = OneUserWithOneOrder().run(db_session)
20 |
21 | order = get_order(OrderId(UUID(order_id)))
22 |
23 | assert order
24 |
25 |
26 | def test_update_order(clean_db: None) -> None:
27 | user_id, order_id = OneUserWithOneOrder().run(db_session)
28 |
29 | update_order(OrderId(UUID(order_id)), order_status=OrderStatus.FailedCredit)
30 |
31 | order = get_order(order_id)
32 |
33 | assert order.order_status == OrderStatus.FailedCredit.value
34 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/storage/test_user.py:
--------------------------------------------------------------------------------
1 | from wallet import storage
2 | from wallet.types import RegistrationStatus
3 | from tests.wallet_tests.resources.seeds.one_user_seeder import OneUser
4 | from wallet.storage import db_session
5 | from diem_utils.types.currencies import DiemCurrency
6 | from datetime import datetime
7 |
8 |
9 | def test_update_user_password_reset_token_expiration():
10 | user = OneUser.run(
11 | db_session, account_amount=100_000_000_000, account_currency=DiemCurrency.XUS
12 | )
13 | now = datetime.now()
14 | updated_user = storage.update_user(
15 | user_id=user.id, password_reset_token_expiration=now
16 | )
17 | assert updated_user.password_reset_token_expiration == now
18 |
19 |
20 | def test_create_user() -> None:
21 | username = "fake_username"
22 | password_hash = "fake_hash"
23 | salt = "fake_salt"
24 | user_id = storage.add_user(
25 | username=username,
26 | password_hash=password_hash,
27 | salt=salt,
28 | registration_status=RegistrationStatus.Pending,
29 | )
30 |
31 | storage_user = storage.get_user(username=username)
32 | assert storage_user
33 | assert storage_user.id == user_id
34 |
--------------------------------------------------------------------------------
/backend/tests/wallet_tests/test_risk.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from wallet.services import risk
7 |
8 |
9 | def test_risk() -> None:
10 | user_id = 1
11 | assert risk.risk_check(user_id, 1)
12 | assert risk.risk_check(user_id, 1000000 * 1000)
13 | assert not risk.risk_check(user_id, 1000000 * 1000 + 1)
14 |
--------------------------------------------------------------------------------
/backend/tests/webapp_tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/tests/webapp_tests/routes/test_rates.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from flask import Response
7 | from flask.testing import Client
8 |
9 |
10 | class TestGetRates:
11 | def test_200(self, authorized_client: Client) -> None:
12 | res: Response = authorized_client.get("/account/rates")
13 | data = res.get_json()
14 | assert res.status_code == 200
15 | assert data["rates"]
16 |
--------------------------------------------------------------------------------
/backend/wallet/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # keep config import first, because we MUST configure dramatiq broker prior to background_tasks import
5 | # once @actor is being used (e.g. in background_tasks) and no global dramatiq broker configured -
6 | # dramatiq will try to use default RabbitMQ one (this is hardcoded and can't be changed) - which will fail
7 |
8 | from . import config
9 | from . import background_tasks
10 |
--------------------------------------------------------------------------------
/backend/wallet/background_tasks/__init__.py:
--------------------------------------------------------------------------------
1 | from .background import *
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
--------------------------------------------------------------------------------
/backend/wallet/security.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import json
5 | from functools import wraps
6 | from http import HTTPStatus
7 |
8 | from flask import g, request, Response
9 |
10 | from .services.user import is_valid_token, revoke_token, get_user_by_token
11 |
12 |
13 | def current_user():
14 | if hasattr(g, "current_user"):
15 | return g.current_user
16 |
17 |
18 | def get_token_id_from_request() -> str:
19 | return request.headers["Authorization"].split()[1]
20 |
21 |
22 | def verify_token(f):
23 | @wraps(f)
24 | def decorated_function(*args, **kwargs):
25 | token_id = get_token_id_from_request()
26 |
27 | if is_valid_token(token_id):
28 | g.current_user = get_user_by_token(token_id)
29 | return f(*args, **kwargs)
30 | else:
31 | revoke_token(token_id)
32 | error = json.dumps(
33 | {
34 | "code": HTTPStatus.UNAUTHORIZED,
35 | "error": "Invalid authorization token",
36 | }
37 | )
38 | return Response(
39 | error, status=HTTPStatus.UNAUTHORIZED, mimetype="application/json"
40 | )
41 |
42 | return decorated_function
43 |
--------------------------------------------------------------------------------
/backend/wallet/services/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import os
5 |
6 | _RUN_BACKGROUND_TASKS = bool(os.getenv("RUN_BACKGROUND_TASKS", True))
7 |
8 |
9 | def run_bg_tasks() -> bool:
10 | return _RUN_BACKGROUND_TASKS
11 |
12 |
13 | INVENTORY_ACCOUNT_NAME = "Inventory"
14 |
--------------------------------------------------------------------------------
/backend/wallet/services/fx/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/backend/wallet/services/log.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from wallet.storage import save_transaction_log
5 |
6 |
7 | def add_transaction_log(transaction_id, log) -> None:
8 | save_transaction_log(transaction_id=transaction_id, log=log)
9 |
--------------------------------------------------------------------------------
/backend/wallet/services/offchain/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/backend/wallet/services/offchain/__init__.py
--------------------------------------------------------------------------------
/backend/wallet/services/risk.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | """ Risk module determines if a transaction by a user can be executed. Risk check is stubbed out for LRW
5 | with a simple amount threshold check. """
6 |
7 | from wallet.logging import log_execution
8 | from wallet.types import UserNotFoundError
9 |
10 | TX_AMOUNT_THRESHOLD = 1_000_000 * 1_000
11 |
12 |
13 | def risk_check(user_id, amount) -> bool:
14 | if user_id is None:
15 | raise UserNotFoundError("Risk check failed with user as None")
16 | if amount <= TX_AMOUNT_THRESHOLD:
17 | log_execution(f"Risk check passed for user {user_id} amount {amount}")
18 | return True
19 |
20 | log_execution(
21 | f"Risk check failed for user {user_id} amount {amount}, need travel rule check"
22 | )
23 | return False
24 |
--------------------------------------------------------------------------------
/backend/wallet/storage/__init__.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from sqlalchemy import MetaData
7 | from sqlalchemy import create_engine
8 | from sqlalchemy.orm import sessionmaker, scoped_session
9 | from sqlalchemy.ext.declarative import declarative_base
10 | from ..config import DB_URL
11 |
12 | connect_args = {}
13 |
14 | if DB_URL.startswith("sqlite"):
15 | connect_args = {"check_same_thread": False}
16 |
17 | engine = create_engine(DB_URL, connect_args=connect_args)
18 | # engine.echo = True
19 | metadata = MetaData()
20 | db_session = scoped_session(
21 | sessionmaker(autocommit=False, autoflush=False, bind=engine)
22 | )
23 |
24 | Base = declarative_base(metadata=metadata)
25 | Base.query = db_session.query_property()
26 |
27 | from .user import *
28 | from .account import *
29 | from .order import *
30 | from .token import *
31 | from .transaction import *
32 | from .logs import *
33 | from .funds_pull_pre_approval_command import *
34 | from .p2p_payment import *
35 | from .p2m_payment import *
36 |
--------------------------------------------------------------------------------
/backend/wallet/storage/logs.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from datetime import datetime
7 | from . import db_session
8 | from .models import ExecutionLog
9 |
10 |
11 | # logs to both database and stdout
12 | def add_execution_log(message) -> None:
13 | # get the previous frame in the stack
14 | log = ExecutionLog(log=message, timestamp=datetime.utcnow())
15 | db_session.add(log)
16 | db_session.commit()
17 |
18 |
19 | def get_execution_logs():
20 | return [log for log in ExecutionLog.query.all()]
21 |
--------------------------------------------------------------------------------
/backend/wallet/storage/p2m_payment.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from . import db_session, models
4 |
5 | logger = logging.getLogger(__name__)
6 |
7 |
8 | def save_payment(payment: models.Payment):
9 | db_session.add(payment)
10 | db_session.commit()
11 |
12 | return payment
13 |
14 |
15 | def get_payment_details(reference_id: str) -> models.Payment:
16 | return models.Payment.query.filter_by(reference_id=reference_id).first()
17 |
18 |
19 | def update_payment(reference_id: str, status: str, recipient_signature: str = None):
20 | payment_in_db = get_payment_details(reference_id)
21 |
22 | if recipient_signature:
23 | payment_in_db.recipient_signature = recipient_signature
24 |
25 | payment_in_db.status = status
26 |
27 | try:
28 | payment_in_db.update(payment_in_db)
29 | db_session.commit()
30 | except Exception as e:
31 | logger.error(error)
32 | raise error
33 |
--------------------------------------------------------------------------------
/backend/wallet/storage/setup.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from wallet.storage import Base, engine
7 |
8 |
9 | def setup_wallet_storage():
10 | Base.metadata.create_all(bind=engine)
11 |
--------------------------------------------------------------------------------
/backend/wallet/storage/token.py:
--------------------------------------------------------------------------------
1 | # pyre-ignore-all-errors
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | from time import time
7 | from uuid import uuid1
8 |
9 | from . import db_session
10 | from .models import Token
11 |
12 |
13 | def get_token(token_id: str):
14 | return Token.query.get(token_id)
15 |
16 |
17 | def create_token(user_id, expiration_time: float) -> str:
18 | token = Token(
19 | user_id=user_id,
20 | expiration_time=expiration_time,
21 | )
22 | db_session.add(token)
23 | db_session.commit()
24 | return token.id
25 |
26 |
27 | def delete_token(token_id) -> None:
28 | token = Token.query.get(token_id)
29 | if token is not None:
30 | db_session.delete(token)
31 | db_session.commit()
32 |
33 |
34 | def delete_user_tokens(user_id) -> None:
35 | Token.query.filter_by(user_id=user_id).delete()
36 | db_session.commit()
37 |
38 |
39 | def update_token(token_id: uuid1, expiration_time: float) -> None:
40 | token = Token.query.get(token_id)
41 | if token is not None:
42 | token.expiration_time = expiration_time
43 | db_session.add(token)
44 | db_session.commit()
45 |
--------------------------------------------------------------------------------
/backend/webapp/debug.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from typing import Union
5 | from flask import (
6 | Blueprint,
7 | render_template,
8 | )
9 | from werkzeug.wrappers import Response
10 | from wallet.storage import get_execution_logs
11 |
12 |
13 | root = Blueprint("root", __name__, url_prefix="/")
14 |
15 |
16 | @root.route("/execution_logs", methods=["GET"])
17 | def list_execution_logs() -> Union[str, Response]:
18 | logs = get_execution_logs()
19 | return render_template("execution_logs.html", logs=logs)
20 |
--------------------------------------------------------------------------------
/backend/webapp/errors.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import traceback
5 | from http import HTTPStatus
6 | from json import JSONDecodeError
7 |
8 | from flask import Blueprint, jsonify, make_response, current_app
9 | from werkzeug.exceptions import HTTPException
10 |
11 | errors = Blueprint("errors", __name__)
12 |
13 |
14 | @errors.app_errorhandler(HTTPException)
15 | def handle_http_exception(error):
16 | """Just logs the error. Any unhandled error will eventually get here."""
17 |
18 | real_error = getattr(error, "original_exception", error)
19 |
20 | current_app.logger.exception(real_error)
21 |
22 | response = {
23 | "code": error.code,
24 | "error": error.description,
25 | }
26 | return make_response(jsonify(response), error.code)
27 |
28 |
29 | @errors.app_errorhandler(JSONDecodeError)
30 | def handle_unexpected_error(error):
31 | status_code = HTTPStatus.BAD_REQUEST
32 | response = {"code": HTTPStatus.BAD_REQUEST, "error": "Could not parse json data"}
33 |
34 | current_app.logger.error(f"error: {error}, exec: {traceback.format_exc()}")
35 |
36 | return make_response(jsonify(response), status_code)
37 |
--------------------------------------------------------------------------------
/backend/webapp/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/backend/webapp/static/favicon.ico
--------------------------------------------------------------------------------
/backend/webapp/templates/execution_logs.html:
--------------------------------------------------------------------------------
1 |
2 |
Global Execution Log
3 |
4 | Global Execution Log
5 | {% if logs %}
6 |
7 | {% for log in logs %}
8 | - [{{ log.timestamp }}] {{ log.log }}
9 | {% endfor %}
10 |
11 | {% else %}
12 | No execution log to show.
13 | {% endif %}
14 |
15 |
--------------------------------------------------------------------------------
/docker/debug.docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | services:
3 | gateway:
4 | image: nginx:1.17-alpine
5 | volumes:
6 | - ../gateway/nginx.debug.conf:/etc/nginx/nginx.conf
7 |
8 | docker-host:
9 | image: qoomon/docker-host
10 | cap_add: [ 'NET_ADMIN', 'NET_RAW' ]
11 | restart: on-failure
12 | environment:
13 | - PORTS=5000
14 |
--------------------------------------------------------------------------------
/docker/dev.docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | services:
3 | gateway:
4 | build:
5 | target: dynamic_conf
6 | volumes:
7 | - ../gateway/nginx.dev.conf:/etc/nginx/nginx.conf
8 |
9 | backend-web-server:
10 | environment:
11 | COMPOSE_ENV: development
12 | ADMIN_LOGIN_ENABLED: 1
13 | ports:
14 | - 5000:5000
15 | volumes:
16 | - ../backend:/wallet
17 | - /wallet/src
18 | - /tmp:/tmp
19 |
20 | backend-worker:
21 | environment:
22 | COMPOSE_ENV: development
23 | volumes:
24 | - ../backend:/wallet
25 | - /wallet/src
26 | - /tmp:/tmp
27 |
28 | backend-pubsub-worker:
29 | environment:
30 | COMPOSE_ENV: development
31 | volumes:
32 | - ../backend:/wallet
33 | - /wallet/src
34 |
35 | liquidity:
36 | environment:
37 | COMPOSE_ENV: development
38 | volumes:
39 | - ../liquidity:/liquidity
40 | - /liquidity/src
41 | ports:
42 | - "5001:5000"
43 |
44 | frontend:
45 | image: lrw_frontend
46 | build:
47 | context: ../frontend
48 | dockerfile: Dockerfile
49 | volumes:
50 | - ../frontend/:/app
51 | - /app/node_modules/
52 |
53 | db:
54 | ports:
55 | - 15432:5432
56 |
--------------------------------------------------------------------------------
/docker/e2e.docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | services:
3 | gateway:
4 | volumes:
5 | - ../gateway/nginx.conf:/etc/nginx/nginx.conf
6 |
7 | backend-web-server:
8 | environment:
9 | - COMPOSE_ENV="development"
10 | ports:
11 | - "5000"
12 |
13 | backend-worker:
14 | environment:
15 | - COMPOSE_ENV="development"
16 |
17 | backend-pubsub-worker:
18 | environment:
19 | - COMPOSE_ENV="development"
20 |
21 | liquidity:
22 | environment:
23 | - COMPOSE_ENV="development"
24 | ports:
25 | - "5000"
26 |
--------------------------------------------------------------------------------
/docker/pg/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM postgres:12.2-alpine
2 |
3 | COPY ./init.d/* /docker-entrypoint-initdb.d/
4 |
--------------------------------------------------------------------------------
/docker/pg/init.d/backend.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | set -e
7 |
8 | LP_DB_NAME="liquidity_provider_db"
9 | DB_NAME="backend_db"
10 | DB_USER="backenduser"
11 | DB_PASSWORD="backendpassword"
12 |
13 | psql -v ON_ERROR_STOP=0 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
14 | CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
15 | CREATE DATABASE $DB_NAME;
16 | GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
17 | EOSQL
18 |
19 | psql -v ON_ERROR_STOP=0 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
20 | CREATE DATABASE $LP_DB_NAME;
21 | GRANT ALL PRIVILEGES ON DATABASE $LP_DB_NAME TO $DB_USER;
22 | EOSQL
23 |
--------------------------------------------------------------------------------
/docker/static.docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | services:
3 | gateway:
4 | build:
5 | target: static_conf
6 | volumes:
7 | - ../gateway/nginx.static.conf:/etc/nginx/nginx.conf
8 |
--------------------------------------------------------------------------------
/format.sh:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | (cd backend && exec pipenv run black .)
5 |
6 | (cd frontend && exec yarn prettier --write .)
7 |
8 | (cd vasp-validator && exec ./lint.sh)
--------------------------------------------------------------------------------
/frontend/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | Dockerfile
--------------------------------------------------------------------------------
/frontend/.env.example:
--------------------------------------------------------------------------------
1 | REACT_APP_BACKEND_URL=/api
2 | REACT_APP_EXPLORER_URL=https://librabrowser.io/version/{version}
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | # JetBrains
26 | .idea
27 |
--------------------------------------------------------------------------------
/frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12.16.2-alpine3.11
2 |
3 | WORKDIR /app
4 | ENV PATH /app/node_modules/.bin:$PATH
5 | RUN npm install -g react-scripts --silent
6 |
7 | COPY package.json yarn.lock /app/
8 | RUN yarn install
9 |
10 | COPY . /app
11 |
12 | RUN CI=true yarn test
13 | RUN yarn build
14 |
15 | CMD yarn start
16 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | # LRW Frontend
2 |
3 | This project is based on [React](https://github.com/facebook/react)
4 |
5 | ## How to use?
6 |
7 | 1. Download or clone this repo.
8 |
9 | 2. Install dependencies.
10 |
11 | ```bash
12 | npm install
13 | // or
14 | yarn install
15 | ```
16 |
17 | 3. Run project on Browser.
18 |
19 | ```bash
20 | npm run start
21 | // or
22 | yarn start
23 | ```
24 |
25 | ## Run tests
26 |
27 | ```bash
28 | npm run test
29 | // or
30 | yarn test
31 | ```
32 |
--------------------------------------------------------------------------------
/frontend/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/frontend/public/favicon.png
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Diem Reference Wallet
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/freesans/FreeSans.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/frontend/src/assets/fonts/freesans/FreeSans.woff
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/freesans/FreeSansBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/frontend/src/assets/fonts/freesans/FreeSansBold.woff
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/freesans/FreeSansBoldOblique.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/frontend/src/assets/fonts/freesans/FreeSansBoldOblique.woff
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/freesans/FreeSansOblique.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/frontend/src/assets/fonts/freesans/FreeSansOblique.woff
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/freesans/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "FreeSans";
3 | font-style: normal;
4 | font-weight: normal;
5 | src: local("FreeSans Medium"), url("FreeSans.woff") format("woff");
6 | }
7 |
8 | @font-face {
9 | font-family: "FreeSans";
10 | font-style: italic;
11 | font-weight: normal;
12 | src: local("FreeSans Oblique"), url("FreeSansOblique.woff") format("woff");
13 | }
14 |
15 | @font-face {
16 | font-family: "FreeSans";
17 | font-style: normal;
18 | font-weight: bold;
19 | src: local("FreeSans Bold"), url("FreeSansBold.woff") format("woff");
20 | }
21 |
22 | @font-face {
23 | font-family: "FreeSans";
24 | font-style: italic;
25 | font-weight: bold;
26 | src: local("FreeSans BoldOblique"), url("FreeSansBoldOblique.woff") format("woff");
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/assets/img/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/assets/scss/_credit-cards.scss:
--------------------------------------------------------------------------------
1 | $rccs-card-ratio: 1.5858;
2 | $rccs-size: 16rem;
3 |
4 | $rccs-name-font-size: 1rem;
5 | $rccs-name-font-family: Consolas, Courier, monospace;
6 | $rccs-number-font-size: 1.15rem;
7 | $rccs-number-font-family: Consolas, Courier, monospace;
8 | $rccs-valid-font-size: 0.65rem;
9 | $rccs-expiry-font-size: 0.9rem;
10 | $rccs-expiry-font-family: Consolas, Courier, monospace;
11 | $rccs-cvc-font-size: 0.9rem;
12 | $rccs-cvc-font-family: Consolas, Courier, monospace;
13 | $rccs-cvc-color: #222;
14 |
--------------------------------------------------------------------------------
/frontend/src/assets/scss/_variables.scss:
--------------------------------------------------------------------------------
1 | $font-family-sans-serif: "FreeSans", "Helvetica Neue", Arial;
2 |
3 | $body-color: #75767f;
4 | $font-size-base: 0.875rem;
5 |
6 | $theme-colors: (
7 | "black": #000000,
8 | "default": #eff1f3,
9 | );
10 |
11 | $headings-color: #000;
12 | $headings-font-weight: 700;
13 | $headings-line-height: 130%;
14 | $headings-margin-bottom: 1rem;
15 |
16 | $primary: #506efa;
17 | $success: #4caf50;
18 | $danger: #ff331f;
19 | $info: #96a8fc;
20 | $text-muted: $body-color;
21 | $link-color: #506efa;
22 | $component-active-bg: #506efa;
23 | $custom-control-indicator-size: 1.25rem;
24 | $border-radius: 0.5rem;
25 |
26 | $btn-font-weight: bold;
27 | $input-bg: #eff1f3;
28 | $input-color: #1a1b29;
29 | $input-placeholder-color: #75767f;
30 | $input-group-addon-bg: #eff1f3;
31 | $input-border-width: 0rem;
32 | $input-btn-padding-y: 0.75rem;
33 | $input-btn-padding-x: 1rem;
34 |
35 | $dropdown-padding-y: 0;
36 | $dropdown-item-padding-y: 0.5rem;
37 | $dropdown-link-color: #000;
38 | $dropdown-link-hover-color: #000;
39 | $dropdown-link-active-color: #000;
40 | $dropdown-link-active-bg: #f5f5f5;
41 |
42 | $alert-padding-y: 0.75rem !default;
43 | $alert-padding-x: 1.25rem !default;
44 | $alert-bg-level: 0;
45 | $alert-border-level: 0;
46 | $alert-border-radius: $border-radius / 2;
47 |
48 | $list-group-border-color: #eff1f3;
49 |
--------------------------------------------------------------------------------
/frontend/src/components/Actions.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { useTranslation } from "react-i18next";
5 | import React from "react";
6 | import { Button } from "reactstrap";
7 |
8 | interface ActionsProps {
9 | onSendClick?: () => void;
10 | onRequestClick?: () => void;
11 | onTransferClick?: () => void;
12 | }
13 |
14 | function Actions({ onSendClick, onRequestClick, onTransferClick }: ActionsProps) {
15 | const { t } = useTranslation("layout");
16 |
17 | return (
18 | <>
19 |
22 |
31 |
34 | >
35 | );
36 | }
37 |
38 | export default Actions;
39 |
--------------------------------------------------------------------------------
/frontend/src/components/Breadcrumbs.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Link } from "react-router-dom";
5 | import React from "react";
6 |
7 | function Breadcrumbs({ pageName }: { pageName: string }) {
8 | return (
9 |
21 | );
22 | }
23 |
24 | export default Breadcrumbs;
25 |
--------------------------------------------------------------------------------
/frontend/src/components/CloseButton.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 |
7 | interface CloseButtonProps {
8 | onClick: () => void;
9 | }
10 |
11 | function CloseButton({ onClick }: CloseButtonProps) {
12 | const { t } = useTranslation("layout");
13 |
14 | return (
15 |
24 | );
25 | }
26 |
27 | export default CloseButton;
28 |
--------------------------------------------------------------------------------
/frontend/src/components/ConfirmationModal.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "reactstrap";
6 |
7 | export interface ConfirmationModalProps {
8 | title: React.ReactNode;
9 | bodyText: string;
10 | cancelText: string;
11 | confirmText: string;
12 | onClose: (confirmed: boolean) => void;
13 | isOpen: boolean;
14 | }
15 |
16 | export default function ConfirmationModal({
17 | title,
18 | bodyText,
19 | cancelText,
20 | confirmText,
21 | onClose,
22 | isOpen,
23 | }: ConfirmationModalProps) {
24 | return (
25 | onClose(false)}>
26 | onClose(false)}>{title}
27 | {bodyText}
28 |
29 | {" "}
32 |
35 |
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/frontend/src/components/ExampleSectionWarning.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 |
7 | const ExampleSectionWarning = () => {
8 | const { t } = useTranslation("legal");
9 |
10 | return (
11 |
12 | {t("example_section_warning")}
13 |
14 | );
15 | };
16 |
17 | export default ExampleSectionWarning;
18 |
--------------------------------------------------------------------------------
/frontend/src/components/Feedback.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Button } from "reactstrap";
6 | import { useTranslation } from "react-i18next";
7 |
8 | const URL =
9 | "https://docs.google.com/forms/d/e/1FAIpQLSfHlFQ4Xz94_9c7ISzdEAPhJ6z1dBXZJ62lF8KGy8u5QoOhMw/viewform";
10 |
11 | function Feedback() {
12 | const { t } = useTranslation("layout");
13 |
14 | return (
15 |
26 | );
27 | }
28 |
29 | export default Feedback;
30 |
--------------------------------------------------------------------------------
/frontend/src/components/Header.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React, { useContext } from "react";
5 | import { useTranslation } from "react-i18next";
6 | import { Link } from "react-router-dom";
7 | import LogoImage from "../assets/img/logo.svg";
8 | import SettingsImage from "../assets/img/gears.svg";
9 | import { settingsContext } from "../contexts/app";
10 |
11 | const Header = () => {
12 | const { t } = useTranslation("layout");
13 | const [settings] = useContext(settingsContext)!;
14 |
15 | return (
16 | <>
17 |
32 |
33 | >
34 | );
35 | };
36 |
37 | export default Header;
38 |
--------------------------------------------------------------------------------
/frontend/src/components/LegalDisclaimer.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 | import { Button } from "reactstrap";
7 |
8 | function LegalDisclaimer({ onClose }: { onClose: () => void }) {
9 | const { t } = useTranslation("legal");
10 |
11 | return (
12 |
13 |
{t("legal_disclaimer")}
14 |
15 |
18 |
19 | );
20 | }
21 |
22 | export default LegalDisclaimer;
23 |
--------------------------------------------------------------------------------
/frontend/src/components/Messages/ErrorMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Alert } from "reactstrap";
5 | import React from "react";
6 |
7 | interface ErrorMessageProps {
8 | message: string;
9 | }
10 |
11 | function ErrorMessage({ message }: ErrorMessageProps) {
12 | return (
13 |
14 | {message}
15 |
16 | );
17 | }
18 |
19 | export default ErrorMessage;
20 |
--------------------------------------------------------------------------------
/frontend/src/components/Messages/InfoMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Alert } from "reactstrap";
6 |
7 | interface InfoMessageProps {
8 | message: string;
9 | }
10 |
11 | function InfoMessage({ message }: InfoMessageProps) {
12 | return (
13 |
14 | {message}
15 |
16 | );
17 | }
18 |
19 | export default InfoMessage;
20 |
--------------------------------------------------------------------------------
/frontend/src/components/Messages/SuccessMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Alert } from "reactstrap";
5 | import React from "react";
6 |
7 | interface SuccessMessageProps {
8 | message: string;
9 | }
10 |
11 | function SuccessMessage({ message }: SuccessMessageProps) {
12 | return (
13 |
14 | {message}
15 |
16 | );
17 | }
18 |
19 | export default SuccessMessage;
20 |
--------------------------------------------------------------------------------
/frontend/src/components/Send/interfaces.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FiatCurrency, DiemCurrency } from "../../interfaces/currencies";
5 |
6 | export interface Send {
7 | currency?: DiemCurrency;
8 | fiatCurrency: FiatCurrency;
9 | amount?: number;
10 | address?: string;
11 | }
12 |
--------------------------------------------------------------------------------
/frontend/src/components/SettlementDetails.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React, { useContext } from "react";
5 | import { settingsContext } from "../contexts/app";
6 | import { diemAmountToHumanFriendly } from "../utils/amount-precision";
7 | import { Debt } from "../interfaces/settlement";
8 |
9 | export interface SettlementDetailsProps {
10 | debt: Debt[];
11 | }
12 |
13 | export default function SettlementDetails({ debt }: SettlementDetailsProps) {
14 | const [settings] = useContext(settingsContext)!;
15 |
16 | return (
17 |
18 | {debt.map(({ currency, amount }) => {
19 | const symbol = settings.fiatCurrencies[currency].sign;
20 | return (
21 | -
25 |
26 | {currency}
27 |
28 |
29 |
30 | {diemAmountToHumanFriendly(amount, true)} {symbol}
31 |
32 |
33 |
34 | );
35 | })}
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/frontend/src/components/SignedUpMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 | import { Spinner } from "reactstrap";
7 |
8 | function SignedUpMessage({ username }: { username: string }) {
9 | const { t } = useTranslation("auth");
10 |
11 | return (
12 | <>
13 | {process.env.NODE_ENV === "production" ? (
14 | <>
15 | {t("signup.success_username.headline")}
16 | {t("signup.success_username.text", { replace: { email: username } })}
17 | >
18 | ) : (
19 | <>
20 | {t("signup.success_email.headline")}
21 | {t("signup.success_email.text", { replace: { username } })}
22 | >
23 | )}
24 |
25 |
26 | {t("signup.redirect", { replace: { username } })}
27 |
28 | >
29 | );
30 | }
31 |
32 | export default SignedUpMessage;
33 |
--------------------------------------------------------------------------------
/frontend/src/components/TestnetWarning.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 |
7 | const TestnetWarning = () => {
8 | const { t } = useTranslation("legal");
9 |
10 | return (
11 |
12 | {t("testnet_warning")}
13 |
14 | );
15 | };
16 |
17 | export default TestnetWarning;
18 |
--------------------------------------------------------------------------------
/frontend/src/components/TotalBalance.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { useTranslation } from "react-i18next";
5 | import React, { useContext } from "react";
6 | import { settingsContext } from "../contexts/app";
7 | import { fiatToDiemHumanFriendly, diemAmountToFloat } from "../utils/amount-precision";
8 |
9 | function TotalBalance() {
10 | const { t } = useTranslation("layout");
11 | const [settings] = useContext(settingsContext)!;
12 |
13 | if (!settings.account) {
14 | return null;
15 | }
16 |
17 | const fiatCurrency = settings.fiatCurrencies[settings.defaultFiatCurrencyCode!];
18 |
19 | const totalFiatBalance = settings.account.balances.reduce((totalBalance, currencyBalance) => {
20 | const exchangeRate =
21 | settings.currencies[currencyBalance.currency].rates[settings.defaultFiatCurrencyCode!];
22 | totalBalance += diemAmountToFloat(currencyBalance.balance) * exchangeRate;
23 | return totalBalance;
24 | }, 0);
25 |
26 | return (
27 | <>
28 |
29 | {fiatCurrency.sign}
30 | {fiatToDiemHumanFriendly(totalFiatBalance, true)} {fiatCurrency.symbol}
31 |
32 | {t("total_balance")}
33 | >
34 | );
35 | }
36 |
37 | export default TotalBalance;
38 |
--------------------------------------------------------------------------------
/frontend/src/components/Transfer/interfaces.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FiatCurrency, DiemCurrency } from "../../interfaces/currencies";
5 |
6 | export interface DepositData extends Record {
7 | fundingSource?: number;
8 | fiatCurrency: FiatCurrency;
9 | currency?: DiemCurrency;
10 | amount?: number;
11 | }
12 |
13 | export interface WithdrawData extends Record {
14 | fundingSource?: number;
15 | fiatCurrency: FiatCurrency;
16 | currency?: DiemCurrency;
17 | amount?: number;
18 | }
19 |
20 | export interface ConvertData extends Record {
21 | fromCurrency?: DiemCurrency;
22 | toCurrency?: DiemCurrency;
23 | amount?: number;
24 | }
25 |
--------------------------------------------------------------------------------
/frontend/src/components/VerifyLoader.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import ContentLoader from "react-content-loader";
6 |
7 | function VerifyLoader() {
8 | return (
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | );
31 | }
32 |
33 | export default VerifyLoader;
34 |
--------------------------------------------------------------------------------
/frontend/src/components/VerifyingMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { useTranslation } from "react-i18next";
6 | import { Spinner } from "reactstrap";
7 |
8 | function VerifyingMessage() {
9 | const { t } = useTranslation("layout");
10 |
11 | return (
12 |
13 | {t("verification_pending.title")}
14 | {t("verification_pending.description")}
15 |
16 |
17 | {t("verification_pending.redirect")}
18 |
19 |
20 | );
21 | }
22 |
23 | export default VerifyingMessage;
24 |
--------------------------------------------------------------------------------
/frontend/src/components/datetime-picker/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import ReactDatetime from "react-datetime";
5 | import React from "react";
6 | import { Moment } from "moment";
7 | import "react-datetime/css/react-datetime.css";
8 |
9 | const DATE_FORMAT = "MM/DD/YYYY";
10 |
11 | interface DateTimeProps {
12 | value?: Moment | string;
13 | onChange?: (value: Moment | string) => void;
14 | placeholder: string;
15 | disabled?: boolean;
16 | invalid?: boolean;
17 | isValidDate?: (currentDate: Moment, selectedDate?: Moment) => boolean;
18 | }
19 |
20 | function DateTimePicker({
21 | value,
22 | onChange,
23 | placeholder,
24 | disabled,
25 | invalid,
26 | isValidDate,
27 | }: DateTimeProps) {
28 | return (
29 |
42 | );
43 | }
44 |
45 | export default DateTimePicker;
46 |
--------------------------------------------------------------------------------
/frontend/src/contexts/app.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { createContext, Dispatch, SetStateAction } from "react";
5 | import { AppSettings } from "../interfaces/settings";
6 |
7 | type SettingsContext = [AppSettings, Dispatch>];
8 |
9 | export const settingsContext = createContext(undefined);
10 |
--------------------------------------------------------------------------------
/frontend/src/contexts/appInitialState.ts:
--------------------------------------------------------------------------------
1 | import { AppSettings } from "../interfaces/settings";
2 |
3 | export const initialState: AppSettings = {
4 | network: "",
5 | currencies: {
6 | XUS: {
7 | name: "XUS",
8 | symbol: "XUS",
9 | sign: "≋XUS",
10 | rates: {
11 | USD: 1,
12 | EUR: 0.85,
13 | GBP: 0.8,
14 | CHF: 1,
15 | CAD: 1,
16 | AUD: 1,
17 | NZD: 1,
18 | JPY: 1,
19 | },
20 | },
21 | },
22 | fiatCurrencies: {
23 | USD: {
24 | symbol: "USD",
25 | sign: "$",
26 | },
27 | EUR: {
28 | symbol: "EUR",
29 | sign: "€",
30 | },
31 | GBP: {
32 | symbol: "GBP",
33 | sign: "£",
34 | },
35 | CHF: {
36 | symbol: "CHF",
37 | sign: "Fr",
38 | },
39 | CAD: {
40 | symbol: "CAD",
41 | sign: "$",
42 | },
43 | AUD: {
44 | symbol: "AUD",
45 | sign: "$",
46 | },
47 | NZD: {
48 | symbol: "NZD",
49 | sign: "$",
50 | },
51 | JPY: {
52 | symbol: "JPY",
53 | sign: "¥",
54 | },
55 | },
56 | user: undefined,
57 | account: undefined,
58 | paymentMethods: undefined,
59 | walletTotals: { balances: [], userCount: -1 },
60 | language: "en",
61 | defaultFiatCurrencyCode: "USD",
62 | };
63 |
--------------------------------------------------------------------------------
/frontend/src/i18n.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import i18next from "i18next";
5 | import { initReactI18next } from "react-i18next";
6 | import LocaleResources from "./locales";
7 |
8 | i18next.use(initReactI18next).init({
9 | interpolation: { escapeValue: false }, // React already does escaping,
10 | lng: "en",
11 | debug: true,
12 | resources: LocaleResources,
13 | });
14 |
15 | export const Languages = Object.keys(LocaleResources);
16 |
17 | export default i18next;
18 |
--------------------------------------------------------------------------------
/frontend/src/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import ReactDOM from "react-dom";
6 | import App from "./App";
7 |
8 | export const isProd = process.env.NODE_ENV === "production";
9 |
10 | ReactDOM.render(, document.getElementById("root"));
11 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/account.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DiemCurrency } from "./currencies";
5 |
6 | export interface CurrencyBalance {
7 | currency: DiemCurrency;
8 | balance: number;
9 | }
10 |
11 | export interface Account {
12 | balances: CurrencyBalance[];
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/approval.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DiemCurrency } from "./currencies";
5 |
6 | type ApprovalStatus = "pending" | "valid" | "rejected" | "closed";
7 |
8 | type ScopeType = "consent" | "save_sub_account";
9 |
10 | type UnitType = "day" | "week" | "month" | "year";
11 |
12 | export interface Approval {
13 | address: string;
14 | biller_address: string;
15 | funds_pull_pre_approval_id: string;
16 | scope: Scope;
17 | description: string;
18 | status: ApprovalStatus;
19 | biller_name: string;
20 | created_at: string;
21 | updated_at: string;
22 | approved_at: string;
23 | }
24 |
25 | interface Scope {
26 | type: ScopeType;
27 | expiration_timestamp: number;
28 | max_cumulative_amount: ScopedCumulativeAmount;
29 | max_transaction_amount: Currency;
30 | }
31 |
32 | interface ScopedCumulativeAmount {
33 | unit: UnitType;
34 | value: number;
35 | max_amount: Currency;
36 | }
37 |
38 | interface Currency {
39 | amount: number;
40 | currency: DiemCurrency;
41 | }
42 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/blockchain.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export const VALID_VASP_ADDRESS_REGEX = new RegExp("^[a-zA-Z0-9]{50}$");
5 |
6 | export const ADDR_PROTOCOL_PREFIX = "diem://";
7 |
8 | export interface VASPAccount {
9 | vasp_name: string;
10 | user_id: string;
11 | full_addr: string;
12 | }
13 |
14 | export interface BlockchainTransaction {
15 | version: number;
16 | status: string;
17 | expirationTime: string;
18 | source: string;
19 | destination: string;
20 | amount: number;
21 | sequenceNumber: number;
22 | }
23 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/cico.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export type QuoteAction = "buy" | "sell";
5 |
6 | export interface RequestForQuote {
7 | action: QuoteAction;
8 | amount: number;
9 | currency_pair: string; // FIXME: specify the supported values
10 | }
11 |
12 | export interface Quote {
13 | quoteId: string;
14 | rfq: RequestForQuote;
15 | price: number;
16 | expirationTime: Date;
17 | }
18 |
19 | export interface Rate {
20 | currency_pair: string;
21 | price: number;
22 | }
23 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/currencies.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export type DiemCurrency = "XUS";
5 |
6 | export type FiatCurrency = "USD" | "EUR" | "GBP" | "CHF" | "CAD" | "AUD" | "NZD" | "JPY";
7 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/payment_details.ts:
--------------------------------------------------------------------------------
1 | export interface PaymentDetails {
2 | action: string;
3 | amount: number;
4 | currency: string;
5 | expiration: number;
6 | merchant_name: string;
7 | reference_id: string;
8 | vasp_address: string;
9 | demo: boolean;
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/settings.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FiatCurrency, DiemCurrency } from "./currencies";
5 | import { PaymentMethod, User } from "./user";
6 | import { Account, CurrencyBalance } from "./account";
7 |
8 | export interface CurrencySettings {
9 | name: string;
10 | symbol: DiemCurrency;
11 | sign: string;
12 | rates: {
13 | [key in FiatCurrency]: number;
14 | };
15 | }
16 |
17 | export interface FiatCurrencySettings {
18 | symbol: FiatCurrency;
19 | sign: string;
20 | }
21 |
22 | export interface WalletTotals {
23 | balances: CurrencyBalance[];
24 | userCount: number;
25 | }
26 |
27 | export interface AppSettings {
28 | network: string;
29 | currencies: {
30 | [key in DiemCurrency]: CurrencySettings;
31 | };
32 | fiatCurrencies: {
33 | [key in FiatCurrency]: FiatCurrencySettings;
34 | };
35 | user?: User;
36 | account?: Account;
37 | language?: string;
38 | defaultFiatCurrencyCode?: FiatCurrency;
39 | paymentMethods?: PaymentMethod[];
40 | walletTotals: WalletTotals;
41 | }
42 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/settlement.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FiatCurrency } from "./currencies";
5 |
6 | export interface Debt {
7 | debt_id: string;
8 | currency: FiatCurrency;
9 | amount: number;
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/system.ts:
--------------------------------------------------------------------------------
1 | export interface Chain {
2 | chain_id: number;
3 | display_name: string;
4 | }
5 |
--------------------------------------------------------------------------------
/frontend/src/interfaces/transaction.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DiemCurrency } from "./currencies";
5 | import { BlockchainTransaction, VASPAccount } from "./blockchain";
6 |
7 | export type TransactionDirection = "received" | "sent";
8 |
9 | export type TransactionStatus = "completed" | "pending" | "canceled" | "locked";
10 |
11 | export interface Transaction {
12 | id: number;
13 | direction: TransactionDirection;
14 | status: TransactionStatus;
15 | currency: DiemCurrency;
16 | source: VASPAccount;
17 | destination: VASPAccount;
18 | amount: number;
19 | blockchain_tx?: BlockchainTransaction;
20 | timestamp: string;
21 | is_internal: boolean;
22 | }
23 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import Layout from "./layout.json";
5 | import Auth from "./auth.json";
6 | import Verify from "./verify.json";
7 | import Transaction from "./transaction.json";
8 | import Send from "./send.json";
9 | import Receive from "./receive.json";
10 | import Transfer from "./transfer.json";
11 | import Validations from "./validations.json";
12 | import Settings from "./settings.json";
13 | import Admin from "./admin.json";
14 | import Legal from "./legal.json";
15 | import FundsPullPreApproval from "./funds_pull_pre_approval.json";
16 | import Payment from "./payment.json";
17 |
18 | export default {
19 | layout: Layout,
20 | auth: Auth,
21 | verify: Verify,
22 | transaction: Transaction,
23 | send: Send,
24 | receive: Receive,
25 | transfer: Transfer,
26 | validations: Validations,
27 | settings: Settings,
28 | admin: Admin,
29 | legal: Legal,
30 | funds_pull_pre_approval: FundsPullPreApproval,
31 | payment: Payment,
32 | };
33 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Diem Wallet",
3 | "total_balance": "Total Balance",
4 | "balances": "Your Balances",
5 | "transactions": "Latest Transactions",
6 | "transactions_empty": "You don’t have any transactions yet. Once you send, request or transfer money, the transactions will appear here.",
7 | "all_transactions": "All Transactions",
8 | "all_transactions_link": "See All",
9 | "all_currencies": "All Currencies",
10 | "price": "Currently equal to",
11 | "close": "Close",
12 | "approvals": "Funds Pull Pre Approvals Requests",
13 | "all_approvals": "See All Approvals",
14 | "actions": {
15 | "send": "Send",
16 | "request": "Request",
17 | "transfer": "Transfer",
18 | "settings": "Settings",
19 | "running_on": "Running on"
20 | },
21 | "verification_pending": {
22 | "title": "Verification Pending",
23 | "description": "Your information is being reviewed. We’ll let you know when it’s complete.",
24 | "redirect": "You will be redirected shortly"
25 | },
26 | "no_payment_methods": {
27 | "title": "You don't have any payment method associated with your account",
28 | "button": "Update now"
29 | },
30 | "feedback": {
31 | "title": "Leave your feedback",
32 | "text": "Feedback"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/legal.json:
--------------------------------------------------------------------------------
1 | {
2 | "legal_disclaimer": "This is a demonstration wallet with no actual users. Do not use any username and/or password you use for other services. Create a test account instead. The compliance processes depicted in this demo wallet are for demonstration purposes only and do not reflect the specific compliance obligations of VASPs under applicable regulatory frameworks, their compliance programs, and/or standards imposed by Diem Networks.",
3 | "example_section_warning": "Example section. No real data required",
4 | "testnet_warning": "This demonstration wallet does not use real money"
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/payment.json:
--------------------------------------------------------------------------------
1 | {
2 | "confirmation": {
3 | "title": "Payment Awaiting Approval",
4 | "title_payment_approved": "Payment Approved!",
5 | "payment_approved": "Your payment to {{merchant}} was completed successfully. You can now safely return to the merchant website",
6 | "summary": "Do you approve payment of {{amount}} {{currency}} to {{merchant}}?",
7 | "amount": "Amount",
8 | "merchant": "Merchant",
9 | "receiver": "Receiver",
10 | "expiration": "Expiration",
11 | "reference_id": "Reference Id",
12 | "approve": "Approve",
13 | "reject": "Reject",
14 | "close": "All Good, back to merchant",
15 | "invalid_payment": "Invalid payment request.",
16 | "processing": "Processing",
17 | "store_name": "Store Name",
18 | "error_occured": "An unexpected error occured. Please try again later."
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/receive.json:
--------------------------------------------------------------------------------
1 | {
2 | "headline": "Select Digital Currency",
3 | "currency_label": "Each one of your digital currencies has a different address.",
4 | "currency": "Currency",
5 | "scan_qr": "Scan QR",
6 | "text": "You can copy your unique Diem Address and give it to the person you’d like to receive money from, or others can read the Diem Address by scanning the QR code.",
7 | "copy": "Copy Address",
8 | "copied": "Copied <1 />"
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/send.json:
--------------------------------------------------------------------------------
1 | {
2 | "success_message": "Your transaction is on the way!",
3 | "fail_message": "Failed to send transaction",
4 | "form": {
5 | "title": "Send Money",
6 | "currency": "currency",
7 | "currency_placeholder": "Select a currency",
8 | "fiatCurrency": "fiat currency",
9 | "amount": "amount",
10 | "price": "currently equal to",
11 | "address": "recipient",
12 | "address_placeholder": "Enter an address",
13 | "exchange_rate": "Exchange rate",
14 | "review": "Review"
15 | },
16 | "review": {
17 | "title": "Review Transaction",
18 | "description": "Please review your transaction. Once you send money, the transaction can’t be reversed.",
19 | "amount": "You’re sending",
20 | "price": "Currently equal to",
21 | "exchange_rate": "Exchange rate",
22 | "address": "To",
23 | "confirm": "Send",
24 | "done": "Done",
25 | "back": "Back"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Settings",
3 | "success_message": "Settings saved successfully!",
4 | "payment_methods": {
5 | "title": "Payment Methods",
6 | "credit_cards": {
7 | "title": "Credit Cards",
8 | "not_found": "You haven't added a credit card yet",
9 | "add": "Add New",
10 | "form": {
11 | "title": "Add Credit Card",
12 | "number": "Card number",
13 | "name": "Name",
14 | "expiry": "Valid Thru",
15 | "cvc": "CVC",
16 | "submit": "Add New Credit Card"
17 | }
18 | },
19 | "bank_accounts": {
20 | "title": "Bank Accounts",
21 | "not_found": "You haven't added a bank account yet",
22 | "add": "Add New",
23 | "form": {
24 | "title": "Add Bank Account",
25 | "account_number": "Account Number",
26 | "bank": "Bank",
27 | "name": "Name",
28 | "submit": "Add New Bank Account"
29 | }
30 | }
31 | },
32 | "preferences": {
33 | "general": {
34 | "title": "General",
35 | "email": "Your email",
36 | "username": "Your username"
37 | },
38 | "form": {
39 | "title": "Preferences",
40 | "fiat_currency": "Local currency",
41 | "language": "Language",
42 | "submit": "Save Settings"
43 | }
44 | },
45 | "signout": "Logout"
46 | }
47 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/transaction.json:
--------------------------------------------------------------------------------
1 | {
2 | "sent": "Sent",
3 | "received": "Received",
4 | "price": "Currently equal to",
5 | "date": "Date",
6 | "to": "to",
7 | "from": "from",
8 | "sent_to": "Sent to",
9 | "sent_from": "Sent from",
10 | "status": "Status",
11 | "tx_id": "Transaction ID",
12 | "internal": "Internal",
13 | "not_available": "Not available",
14 | "locked_status": "Locked"
15 | }
16 |
--------------------------------------------------------------------------------
/frontend/src/locales/en/validations.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": "Please enter {{field}}",
3 | "min": "Please enter {{field}} above {{min}}",
4 | "max": "Please enter {{field}} below {{max}}",
5 | "minLength": "Please enter {{field}} longer than {{minLength}}",
6 | "maxLength": "Please enter {{field}} shorter than {{maxLength}}",
7 | "pattern": "Please enter valid {{field}}",
8 | "numbersOnly": "Please enter {{field}} with numbers only",
9 | "validDate": "Please enter a valid date",
10 | "pastDateOnly": "Please enter a date in the past",
11 | "noEqualCurrencies": "Please select different currencies",
12 | "noMoreThanBalance": "Please enter {{field}} less than your current {{currency}} balance",
13 | "passwordsDontMatch": "Passwords do not match"
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import Layout from "./layout.json";
5 | import Auth from "./auth.json";
6 | import Verify from "./verify.json";
7 | import Transaction from "./transaction.json";
8 | import Send from "./send.json";
9 | import Receive from "./receive.json";
10 | import Transfer from "./transfer.json";
11 | import Validations from "./validations.json";
12 | import Settings from "./settings.json";
13 | import Admin from "./admin.json";
14 | import FundsPullPreApproval from "./funds_pull_pre_approval.json";
15 |
16 | export default {
17 | layout: Layout,
18 | auth: Auth,
19 | verify: Verify,
20 | transaction: Transaction,
21 | send: Send,
22 | receive: Receive,
23 | transfer: Transfer,
24 | validations: Validations,
25 | settings: Settings,
26 | admin: Admin,
27 | funds_pull_pre_approval: FundsPullPreApproval,
28 | };
29 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cartera Diem",
3 | "total_balance": "Saldo Total",
4 | "balances": "Ver sus saldos",
5 | "transactions": "'Últimas transacciones'",
6 | "transactions_empty": "Aún no tienes ninguna transacción. Una vez que envíe, solicite o transfiera dinero, las transacciones aparecerán aquí.",
7 | "all_transactions": "Todas las Transacciones",
8 | "all_transactions_link": "Ver todo",
9 | "all_currencies": "Todas las monedas",
10 | "price": "Actualmente igual a",
11 | "close": "Cerrar",
12 | "actions": {
13 | "send": "Enviar",
14 | "request": "Solicitud",
15 | "transfer": "Transferir",
16 | "settings": "Ajustes"
17 | },
18 | "verification_pending": {
19 | "title": "Verificación pendiente",
20 | "description": "Su información está siendo revisada. Te avisaremos cuando esté completo."
21 | },
22 | "feedback": {
23 | "title": "Deje sus comentarios",
24 | "text": "Commentarios"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/payment.json:
--------------------------------------------------------------------------------
1 | {
2 | "confirmation": {
3 | "title": "Payment Awaiting Approval",
4 | "title_payment_approved": "Payment Approved!",
5 | "payment_approved": "Your payment to {{merchant}} was completed successfully. You can now safely return to the merchant website",
6 | "summary": "Do you approve payment of {{amount}} {{currency}} to {{merchant}}?",
7 | "amount": "Amount",
8 | "merchant": "Merchant",
9 | "receiver": "Receiver",
10 | "expiration": "Expiration",
11 | "reference_id": "Reference Id",
12 | "approve": "Approve",
13 | "reject": "Reject",
14 | "close": "All Good, back to merchant",
15 | "invalid_payment": "Invalid payment request.",
16 | "processing": "Processing",
17 | "error_occured": "An unexpected error occured. Please try again later."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/receive.json:
--------------------------------------------------------------------------------
1 | {
2 | "headline": "Seleccionar moneda digital",
3 | "currency_label": "Cada una de sus monedas digitales tiene una dirección diferente.",
4 | "currency": "Currency",
5 | "scan_qr": "Escanea el código QR",
6 | "text": "Puede copiar su dirección única y dársela a la persona de la que desea recibir dinero. O otros pueden leer la dirección escaneando el código QR.",
7 | "copy": "Copiar dirección",
8 | "copied": "Copiado <1 />"
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/send.json:
--------------------------------------------------------------------------------
1 | {
2 | "success_message": "Su transacción está en camino!",
3 | "fail_message": "Error al enviar la transacción",
4 | "form": {
5 | "title": "Enviar Dinero a Usuario",
6 | "currency": "moneda",
7 | "currency_placeholder": "Selecciona una moneda",
8 | "fiatCurrency": "Moneda Fiat",
9 | "amount": "importe",
10 | "price": "actualmente igual a",
11 | "address": "receptor",
12 | "address_placeholder": "Ingresar Dirección",
13 | "exchange_rate": "Tipo de cambio",
14 | "review": "Revisión"
15 | },
16 | "review": {
17 | "title": "Revisar transacción",
18 | "description": "Por favor revise su transacción. Una vez que envía dinero, la transacción no se puede revertir.",
19 | "amount": "Estas enviando",
20 | "price": "Actualmente igual a",
21 | "exchange_rate": "Tipo de cambio",
22 | "address": "Para",
23 | "confirm": "Enviar",
24 | "done": "Hecho",
25 | "back": "Atrás"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/transaction.json:
--------------------------------------------------------------------------------
1 | {
2 | "sent": "Enviado",
3 | "received": "Recibido",
4 | "price": "Actualmente igual a",
5 | "date": "Fecha",
6 | "to": "a",
7 | "from": "desde",
8 | "sent_to": "Enviar a",
9 | "sent_from": "Enviado desde",
10 | "status": "Estado",
11 | "tx_id": "ID de transacción de Diem",
12 | "internal": "Interna",
13 | "not_available": "No disponible"
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/src/locales/es/validations.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": "Por favor, complete el campo:",
3 | "min": "Ingrese {{field}} arriba {{min}}",
4 | "max": "Ingrese {{field}} debajo de {{max}}",
5 | "minLength": "Ingrese {{field}} más de {{minLength}}",
6 | "maxLength": "Ingrese {{field}} más corto que {{maxLength}}",
7 | "pattern": "Introduzca el campo válido",
8 | "numbersOnly": "Ingrese {{field}} solo con números",
9 | "validDate": "Por favor, introduzca una fecha válida",
10 | "pastDateOnly": "Por favor introduce una fecha de inicio en el pasado.",
11 | "noEqualCurrencies": "Por favor seleccione diferentes monedas",
12 | "noMoreThanBalance": "Ingrese {{field}} menos que su saldo actual de {{currency}}",
13 | "passwordsDontMatch": "Las contraseñas no concuerdan"
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/src/locales/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Resource } from "i18next";
5 | import EN from "./en";
6 | import ES from "./es";
7 |
8 | export default {
9 | en: EN,
10 | es: ES,
11 | } as Resource;
12 |
--------------------------------------------------------------------------------
/frontend/src/pages/VerifySteps/interfaces.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Moment } from "moment";
5 | import { FiatCurrency } from "../../interfaces/currencies";
6 |
7 | export interface IdentityInfo extends Record {
8 | first_name: string;
9 | last_name: string;
10 | dob: string | Moment;
11 | phone_prefix: string;
12 | phone_number: string;
13 | }
14 |
15 | export interface CountryInfo extends Record {
16 | country: string;
17 | }
18 |
19 | export interface AddressInfo extends Record {
20 | address_1: string;
21 | address_2: string;
22 | city: string;
23 | state: string;
24 | zip: string;
25 | }
26 |
27 | export interface DefaultSettings extends Record {
28 | default_fiat_currency: FiatCurrency;
29 | }
30 |
--------------------------------------------------------------------------------
/frontend/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | ///
5 |
--------------------------------------------------------------------------------
/frontend/src/services/errors.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export interface ErrorMessage {
5 | error: string;
6 | code: number;
7 | }
8 |
9 | export class BackendError extends Error {
10 | constructor(message: string, public httpStatus: number) {
11 | super(message);
12 | }
13 | }
14 |
15 | export class UsernameAlreadyExistsError extends Error {}
16 |
--------------------------------------------------------------------------------
/frontend/src/services/sessionStorage.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | class SessionStorage {
5 | storeAccessToken(token: string): void {
6 | window.localStorage.setItem("token", token);
7 | }
8 |
9 | getAccessToken(): string | undefined {
10 | const token = window.localStorage.getItem("token");
11 | if (!token) {
12 | return undefined;
13 | }
14 | return token;
15 | }
16 |
17 | removeAccessToken(): void {
18 | window.localStorage.removeItem("token");
19 | }
20 | }
21 |
22 | export default new SessionStorage();
23 |
--------------------------------------------------------------------------------
/frontend/src/utils/auth-routes.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import SessionStorage from "../services/sessionStorage";
5 | import { Redirect, Route, useLocation } from "react-router-dom";
6 | import React from "react";
7 |
8 | export const LoggedInRoute = ({ component: Component, ...rest }) => {
9 | const queryString = useLocation().search;
10 |
11 | const loggedIn = !!SessionStorage.getAccessToken();
12 | return (
13 |
16 | loggedIn ? :
17 | }
18 | />
19 | );
20 | };
21 |
22 | export const LoggedOutRoute = ({ component: Component, ...rest }) => {
23 | const loggedOut = !SessionStorage.getAccessToken();
24 | return (
25 | (loggedOut ? : )}
28 | />
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/frontend/src/utils/class-names.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export function classNames(classes: object): string {
5 | return Object.entries(classes)
6 | .filter((e) => e[1])
7 | .map((e) => e[0])
8 | .join(" ");
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "noImplicitAny": false,
6 | "allowJs": true,
7 | "skipLibCheck": true,
8 | "esModuleInterop": true,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react",
18 | "baseUrl": "src"
19 | },
20 | "include": ["src"]
21 | }
22 |
--------------------------------------------------------------------------------
/gateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:1.17-alpine as dynamic_conf
2 |
3 | #-------------------------------------------------------------------
4 | FROM dynamic_conf as default_conf
5 | COPY nginx.conf /etc/nginx/nginx.conf
6 | COPY tmp/frontend/. /html/
7 |
8 | #-------------------------------------------------------------------
9 | FROM default_conf as static_conf
10 | COPY nginx.static.conf /etc/nginx/nginx.conf
--------------------------------------------------------------------------------
/gateway/nginx.conf:
--------------------------------------------------------------------------------
1 | events {
2 | worker_connections 4096; ## Default: 1024
3 | }
4 |
5 | http {
6 | server {
7 | include /etc/nginx/mime.types;
8 | server_name reference-wallet;
9 | listen 8000;
10 | keepalive_timeout 70;
11 |
12 | location /api/ {
13 | proxy_set_header X-Real-IP $remote_addr;
14 | proxy_set_header Host $host;
15 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
16 | proxy_set_header X-Forwarded-Prefix /api/;
17 | proxy_redirect off;
18 | proxy_pass http://backend-web-server:5000/;
19 | }
20 |
21 | location / {
22 | root /html;
23 | try_files $uri $uri/ /index.html;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gateway/nginx.debug.conf:
--------------------------------------------------------------------------------
1 | events {
2 | worker_connections 4096; ## Default: 1024
3 | }
4 |
5 | http {
6 | server {
7 | resolver 127.0.0.11 valid=30s;
8 | include /etc/nginx/mime.types;
9 | server_name reference-wallet;
10 | listen 8000;
11 | keepalive_timeout 70;
12 |
13 | location /api/ {
14 | proxy_set_header X-Real-IP $remote_addr;
15 | proxy_set_header Host $host;
16 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
17 | proxy_set_header X-Forwarded-Prefix /api/;
18 | proxy_redirect off;
19 | proxy_pass http://docker-host:5000/;
20 | }
21 |
22 | location / {
23 | set $frontend_uptstream http://frontend:3000;
24 | proxy_set_header X-Real-IP $remote_addr;
25 | proxy_set_header Host $host;
26 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
27 | proxy_redirect off;
28 | proxy_pass $frontend_uptstream;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/gateway/nginx.dev.conf:
--------------------------------------------------------------------------------
1 | error_log /var/log/nginx/error.log notice;
2 |
3 | events {
4 | worker_connections 4096; ## Default: 1024
5 | }
6 |
7 | http {
8 | log_format verbose_log '[$time_local] $status '
9 | '$request -> $proxy_host '
10 | '"$http_referer" "$http_user_agent"';
11 | access_log /var/log/nginx/access.log verbose_log;
12 |
13 | server {
14 | resolver 127.0.0.11 valid=30s;
15 | include /etc/nginx/mime.types;
16 | server_name reference-wallet;
17 | listen 8000;
18 | keepalive_timeout 70;
19 |
20 | location /api/ {
21 | proxy_set_header X-Real-IP $remote_addr;
22 | proxy_set_header Host $host;
23 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
24 | proxy_set_header X-Forwarded-Prefix /api/;
25 | proxy_redirect off;
26 | proxy_pass http://backend-web-server:5000/;
27 | }
28 |
29 | location / {
30 | set $frontend_uptstream http://frontend:3000;
31 | proxy_set_header X-Real-IP $remote_addr;
32 | proxy_set_header Host $host;
33 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
34 | proxy_redirect off;
35 | proxy_pass $frontend_uptstream;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/gateway/nginx.static.conf:
--------------------------------------------------------------------------------
1 | events {
2 | worker_connections 4096; ## Default: 1024
3 | }
4 |
5 | http {
6 | server {
7 | include /etc/nginx/mime.types;
8 | server_name reference-wallet;
9 | listen 8080;
10 | keepalive_timeout 70;
11 |
12 | location / {
13 | root /html;
14 | try_files $uri $uri/ /index.html;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/helm/reference-wallet/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/helm/reference-wallet/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: reference-wallet
3 | version: 1.0.0
4 | description: A Helm chart for Diem Reference Wallet
5 | type: application
6 | home: https://github.com/diem/reference-wallet
7 | icon: https://github.com/diem/diem/raw/master/developers.diem.com/static/img/diem-logo.png
8 |
--------------------------------------------------------------------------------
/helm/reference-wallet/templates/frontend-service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ include "reference-wallet.fullname" . }}-frontend
5 | labels:
6 | {{- include "reference-wallet.labels" . | nindent 4 }}
7 | app: {{ include "reference-wallet.fullname" . }}-frontend
8 | spec:
9 | type: {{ .Values.service.type }}
10 | ports:
11 | - port: {{ .Values.service.port }}
12 | targetPort: {{ .Values.service.targetPort }}
13 | protocol: TCP
14 | name: http
15 | selector:
16 | {{- include "reference-wallet.selectorLabels" . | nindent 4 }}
17 | app: {{ include "reference-wallet.fullname" . }}-frontend
18 |
--------------------------------------------------------------------------------
/helm/reference-wallet/templates/peripherals-service.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.peripherals.redis.create -}}
2 | apiVersion: v1
3 | kind: Service
4 | metadata:
5 | name: {{ include "reference-wallet.fullname" . }}-redis
6 | labels:
7 | app: {{ include "reference-wallet.fullname" . }}-redis
8 | {{- include "reference-wallet.labels" . | nindent 4 }}
9 | spec:
10 | selector:
11 | app: {{ include "reference-wallet.fullname" . }}-redis
12 | {{- include "reference-wallet.selectorLabels" . | nindent 4 }}
13 | ports:
14 | - protocol: "TCP"
15 | port: {{ .Values.peripherals.redis.port }}
16 | targetPort: {{ .Values.peripherals.redis.port }}
17 | name: redis
18 | ---
19 | {{- end }}
20 | {{- if .Values.peripherals.database.create -}}
21 | apiVersion: v1
22 | kind: Service
23 | metadata:
24 | name: {{ include "reference-wallet.fullname" . }}-db
25 | labels:
26 | app: {{ include "reference-wallet.fullname" . }}-db
27 | {{- include "reference-wallet.labels" . | nindent 4 }}
28 | spec:
29 | selector:
30 | app: {{ include "reference-wallet.fullname" . }}-db
31 | {{- include "reference-wallet.selectorLabels" . | nindent 4 }}
32 | ports:
33 | - protocol: "TCP"
34 | port: {{ .Values.peripherals.database.port }}
35 | targetPort: {{ .Values.peripherals.database.port }}
36 | name: db
37 | ---
38 | {{- end }}
39 |
--------------------------------------------------------------------------------
/helm/reference-wallet/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.serviceAccount.create -}}
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: {{ include "reference-wallet.serviceAccountName" . }}
6 | labels:
7 | {{- include "reference-wallet.labels" . | nindent 4 }}
8 | {{- with .Values.serviceAccount.annotations }}
9 | annotations:
10 | {{- toYaml . | nindent 4 }}
11 | {{- end }}
12 | {{- end }}
13 |
--------------------------------------------------------------------------------
/mobile/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/mobile/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/mobile/.env.example:
--------------------------------------------------------------------------------
1 | BACKEND_URL=
2 | EXPLORER_URL=https://librabrowser.io/version/{version}
3 |
--------------------------------------------------------------------------------
/mobile/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: '@react-native-community',
4 | parser: '@typescript-eslint/parser',
5 | plugins: ['@typescript-eslint'],
6 | };
7 |
--------------------------------------------------------------------------------
/mobile/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/mobile/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 |
32 | # Visual Studio Code
33 | #
34 | .vscode/
35 |
36 | # node.js
37 | #
38 | node_modules/
39 | npm-debug.log
40 | yarn-error.log
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 | !debug.keystore
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/
54 |
55 | */fastlane/report.xml
56 | */fastlane/Preview.html
57 | */fastlane/screenshots
58 |
59 | # Bundle artifact
60 | *.jsbundle
61 |
62 | # CocoaPods
63 | /ios/Pods/
64 |
--------------------------------------------------------------------------------
/mobile/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: false,
3 | jsxBracketSameLine: true,
4 | singleQuote: true,
5 | trailingComma: 'all',
6 | };
7 |
--------------------------------------------------------------------------------
/mobile/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/mobile/README.md:
--------------------------------------------------------------------------------
1 | # LRW Mobile
2 |
3 | This project is based on [React Native](https://github.com/facebook/react-native)
4 |
5 | ## How to use?
6 |
7 | 1. Download or clone this repo.
8 | 2. Make sure your development environment is configured as described in the [React Native documentation](https://reactnative.dev/docs/environment-setup)
9 | 3. Install dependencies:
10 |
11 | ```sh
12 | yarn install
13 | ```
14 |
15 | 4. Run the bundler:
16 |
17 | ```sh
18 | yarn start
19 | ```
20 | 5. While the bundler is running in its own terminal, run start the app on iOS/Android:
21 |
22 | ```sh
23 | yarn ios
24 | yarn android
25 | ```
26 |
--------------------------------------------------------------------------------
/mobile/__tests__/App-test.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | /**
5 | * @format
6 | */
7 |
8 | import 'react-native';
9 | import React from 'react';
10 | import App from '../src/App';
11 |
12 | // Note: test renderer must be required after react-native.
13 | import renderer from 'react-test-renderer';
14 |
15 | it('renders correctly', () => {
16 | renderer.create();
17 | });
18 |
--------------------------------------------------------------------------------
/mobile/android/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM circleci/android:api-29-node
2 |
3 |
4 | RUN gem install fastlane -NV
5 | RUN sdkmanager --install \
6 | "ndk;21.3.6528147" \
7 | "cmake;3.10.2.4988404"
8 |
--------------------------------------------------------------------------------
/mobile/android/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "fastlane"
4 |
--------------------------------------------------------------------------------
/mobile/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/mobile/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/debug.keystore
--------------------------------------------------------------------------------
/mobile/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/mobile/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/AntDesign.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/AntDesign.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Entypo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Entypo.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/EvilIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/EvilIcons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Feather.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Feather.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FontAwesome.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FontAwesome.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Fontisto.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Fontisto.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Foundation.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Foundation.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FreeSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FreeSans-Bold.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/FreeSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/FreeSans-Regular.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Ionicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Ionicons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/MaterialIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/MaterialIcons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Octicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Octicons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/SimpleLineIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/SimpleLineIcons.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/assets/fonts/Zocial.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/assets/fonts/Zocial.ttf
--------------------------------------------------------------------------------
/mobile/android/app/src/main/java/com/lrw/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.lrw;
2 |
3 | import com.reactnativenavigation.NavigationActivity;
4 |
5 | public class MainActivity extends NavigationActivity {
6 |
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LRW
3 |
4 |
--------------------------------------------------------------------------------
/mobile/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/mobile/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | RNNKotlinVersion = "1.3.61"
6 | buildToolsVersion = "29.0.3"
7 | minSdkVersion = 19
8 | compileSdkVersion = 29
9 | targetSdkVersion = 29
10 | }
11 | repositories {
12 | google()
13 | jcenter()
14 | }
15 | dependencies {
16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
17 | classpath('com.android.tools.build:gradle:4.0.0')
18 |
19 | // NOTE: Do not place your application dependencies here; they belong
20 | // in the individual module build.gradle files
21 | }
22 | }
23 |
24 | allprojects {
25 | repositories {
26 | mavenLocal()
27 | maven {
28 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
29 | url("$rootDir/../node_modules/react-native/android")
30 | }
31 | maven {
32 | // Android JSC is installed from npm
33 | url("$rootDir/../node_modules/jsc-android/dist")
34 | }
35 |
36 | google()
37 | jcenter()
38 | maven { url 'https://www.jitpack.io' }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/mobile/android/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | json_key_file("/tmp/key.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
2 | package_name("com.lrw") # e.g. com.krausefx.app
3 |
--------------------------------------------------------------------------------
/mobile/android/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ================
3 | # Installation
4 |
5 | Make sure you have the latest version of the Xcode command line tools installed:
6 |
7 | ```
8 | xcode-select --install
9 | ```
10 |
11 | Install _fastlane_ using
12 | ```
13 | [sudo] gem install fastlane -NV
14 | ```
15 | or alternatively using `brew cask install fastlane`
16 |
17 | # Available Actions
18 | ## Android
19 | ### android test
20 | ```
21 | fastlane android test
22 | ```
23 | Runs all the tests
24 | ### android beta
25 | ```
26 | fastlane android beta
27 | ```
28 | Submit a new Beta Build to Play Store
29 |
30 | ----
31 |
32 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
33 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
34 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
35 |
--------------------------------------------------------------------------------
/mobile/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.33.1
29 |
--------------------------------------------------------------------------------
/mobile/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/mobile/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun May 31 10:48:37 IDT 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/mobile/android/publish.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | if [[ -z ${LRW_KEYSTORE_B64+x} ]]; then
7 | echo "no keystore (base64) supplied in LRW_KEYSTORE_B64"
8 | exit -1
9 | fi
10 |
11 | if [[ -z ${GOOGLE_SERVICE_ACCOUNT_B64+x} ]]; then
12 | echo "no google service account key json (base64) supplied in GOOGLE_SERVICE_ACCOUNT_B64"
13 | exit -1
14 | fi
15 |
16 | if [[ -z ${STORE_PASSWORD+x} ]]; then
17 | echo "no keystore password supplied in STORE_PASSWORD"
18 | exit -1
19 | fi
20 |
21 | if [[ -z ${KEY_PASSWORD+x} ]]; then
22 | echo "no key entry (alias) password supplied in KEY_PASSWORD"
23 | exit -1
24 | fi
25 |
26 | if [[ -z ${VERSION_CODE+x} ]]; then
27 | echo "no version code supplied in VERSION_CODE"
28 | exit -1
29 | fi
30 |
31 | echo ${GOOGLE_SERVICE_ACCOUNT_B64} | base64 -d > /tmp/key.json
32 | echo ${LRW_KEYSTORE_B64} | base64 -d > /tmp/lrw-release-key.keystore
33 |
34 |
35 | fastlane beta
--------------------------------------------------------------------------------
/mobile/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "LRW",
3 | "displayName": "LRW"
4 | }
--------------------------------------------------------------------------------
/mobile/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["module:metro-react-native-babel-preset"],
3 | plugins: ["transform-inline-environment-variables"],
4 | };
5 |
--------------------------------------------------------------------------------
/mobile/ios/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "fastlane"
4 |
--------------------------------------------------------------------------------
/mobile/ios/LRW.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/mobile/ios/LRW.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/mobile/ios/LRW/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/1024.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/120-1.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/120.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/180.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/40.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/58.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/60.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/80.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/Images.xcassets/AppIcon.appiconset/87.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/1024.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/120.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/180.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/40.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/58.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/60.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/80.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/icons/87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/ios/LRW/icons/87.png
--------------------------------------------------------------------------------
/mobile/ios/LRW/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/mobile/ios/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | apple_id(ENV["APPLE_ID"])
2 | app_identifier(ENV["APPLE_APP_IDENTIFIER"])
3 | team_id(ENV["APPLE_TEAM_ID"]) # Developer Portal Team ID
4 |
--------------------------------------------------------------------------------
/mobile/ios/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | #
6 | # https://docs.fastlane.tools/actions
7 | #
8 | # For a list of all available plugins, check out
9 | #
10 | # https://docs.fastlane.tools/plugins/available-plugins
11 | #
12 |
13 | # Uncomment the line if you want fastlane to automatically update itself
14 | # update_fastlane
15 |
16 | default_platform(:ios)
17 |
18 | platform :ios do
19 | before_all do
20 | setup_circle_ci
21 | end
22 | desc "Upload to Testflight"
23 | lane :beta do
24 | increment_build_number(
25 | build_number: latest_testflight_build_number(
26 | initial_build_number: 1,
27 | version: get_version_number(xcodeproj: "LRW.xcodeproj")
28 | ) + 1,
29 | )
30 | match(type: "appstore")
31 | gym(scheme: "LRW", xcargs: "PROVISIONING_PROFILE_SPECIFIER='#{ENV['PROVISIONING_PROFILE']}'")
32 | pilot(
33 | distribute_external: true,
34 | notify_external_testers: false,
35 | changelog: "CircleCI build"
36 | )
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/mobile/ios/fastlane/Matchfile:
--------------------------------------------------------------------------------
1 | git_url(ENV["FASTLANE_MATCH_REPO"])
2 |
3 | storage_mode("git")
4 |
5 | type("development") # The default type, can be: appstore, adhoc, enterprise or development
6 | keychain_password(ENV["FASTLANE_KEYCHAIN_PWD"])
7 | app_identifier([ENV["APPLE_APP_IDENTIFIER"]])
8 | username(ENV["APPLE_ID"]) # Your Apple Developer Portal username
9 |
10 |
--------------------------------------------------------------------------------
/mobile/ios/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ================
3 | # Installation
4 |
5 | Make sure you have the latest version of the Xcode command line tools installed:
6 |
7 | ```
8 | xcode-select --install
9 | ```
10 |
11 | Install _fastlane_ using
12 | ```
13 | [sudo] gem install fastlane -NV
14 | ```
15 | or alternatively using `brew cask install fastlane`
16 |
17 | # Available Actions
18 | ## iOS
19 | ### ios beta
20 | ```
21 | fastlane ios beta
22 | ```
23 | Upload to Testflight
24 |
25 | ----
26 |
27 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
28 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
29 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
30 |
--------------------------------------------------------------------------------
/mobile/ios/publish.sh:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | #!/usr/bin/env bash
5 |
6 | if [[ -z ${APPLE_ID+x} ]]; then
7 | echo "no apple id supplied in APPLE_ID"
8 | exit -1
9 | fi
10 |
11 | if [[ -z ${APPLE_APP_IDENTIFIER+x} ]]; then
12 | echo "no apple application identifier (app id) supplied in APPLE_APP_IDENTIFIER"
13 | exit -1
14 | fi
15 |
16 | if [[ -z ${APPLE_TEAM_ID+x} ]]; then
17 | echo "no apple team id supplied in APPLE_TEAM_ID"
18 | exit -1
19 | fi
20 |
21 | if [[ -z ${FASTLANE_MATCH_REPO+x} ]]; then
22 | echo "no fastlane match repo (git url with access token) supplied in FASTLANE_MATCH_REPO"
23 | exit -1
24 | fi
25 |
26 | if [[ -z ${FASTLANE_KEYCHAIN_PWD+x} ]]; then
27 | echo "no fastlane keychain password supplied in FASTLANE_KEYCHAIN_PWD"
28 | exit -1
29 | fi
30 |
31 | if [[ -z ${MATCH_PASSWORD+x} ]]; then
32 | echo "no fastlane match storage passphrase supplied in MATCH_PASSWORD"
33 | exit -1
34 | fi
35 |
36 | if [[ -z ${PROVISIONING_PROFILE+x} ]]; then
37 | echo "no xcode provisioning profile specifier supplied in PROVISIONING_PROFILE"
38 | exit -1
39 | fi
40 |
41 | #cd ..
42 | #npx yarn build:ios
43 | #
44 | #cd ios
45 | bundle exec fastlane beta --verbose
46 |
--------------------------------------------------------------------------------
/mobile/metro.config.js:
--------------------------------------------------------------------------------
1 | const {getDefaultConfig} = require('metro-config');
2 |
3 | module.exports = (async () => {
4 | const {
5 | resolver: {sourceExts, assetExts},
6 | } = await getDefaultConfig();
7 | return {
8 | transformer: {
9 | babelTransformerPath: require.resolve('react-native-svg-transformer'),
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false,
14 | },
15 | }),
16 | },
17 | resolver: {
18 | assetExts: assetExts.filter((ext) => ext !== 'svg'),
19 | sourceExts: [...sourceExts, 'svg'],
20 | },
21 | };
22 | })();
23 |
--------------------------------------------------------------------------------
/mobile/react-native.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | project: {
3 | ios: {},
4 | android: {},
5 | },
6 | assets: ["./src/assets/fonts/freesans/"],
7 | };
8 |
--------------------------------------------------------------------------------
/mobile/src/assets/back-arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/mobile/src/assets/chevron.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/mobile/src/assets/fonts/freesans/FreeSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/src/assets/fonts/freesans/FreeSans-Bold.ttf
--------------------------------------------------------------------------------
/mobile/src/assets/fonts/freesans/FreeSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/src/assets/fonts/freesans/FreeSans-Regular.ttf
--------------------------------------------------------------------------------
/mobile/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diem/reference-wallet/e8efec4acc6af6e319cf075c10693ddf7754cc83/mobile/src/assets/logo.png
--------------------------------------------------------------------------------
/mobile/src/components/DatePicker.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import ReactDatePicker from "react-native-datepicker";
6 | import { ThemeConsumer } from "react-native-elements";
7 | import { appTheme } from "../styles";
8 |
9 | interface DatePickerProps {
10 | value?: string | Date;
11 | placeholder?: string;
12 | onChange?: (dateStr: string, date: Date) => void;
13 | maxDate?: string | Date;
14 | disabled?: boolean;
15 | }
16 |
17 | function DatePicker({ value, placeholder, onChange, maxDate, disabled }: DatePickerProps) {
18 | return (
19 | >
20 | {({ theme }) => (
21 |
35 | )}
36 |
37 | );
38 | }
39 |
40 | export default DatePicker;
41 |
--------------------------------------------------------------------------------
/mobile/src/components/ExampleSectionWarning.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { View } from "react-native";
6 | import { Text, ThemeConsumer } from "react-native-elements";
7 | import { useTranslation } from "react-i18next";
8 | import { appTheme } from "../styles";
9 |
10 | function ExampleSectionWarning() {
11 | const { t } = useTranslation("legal");
12 |
13 | return (
14 | >
15 | {({ theme }) => (
16 |
17 | {t("example_section_warning")}
18 |
19 | )}
20 |
21 | );
22 | }
23 |
24 | export default ExampleSectionWarning;
25 |
--------------------------------------------------------------------------------
/mobile/src/components/ExplorerLink.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { BlockchainTransaction } from "../interfaces/blockchain";
5 | import { Text, ThemeConsumer } from "react-native-elements";
6 | import React from "react";
7 | import { Linking, TouchableOpacity } from "react-native";
8 | import { appTheme } from "../styles";
9 |
10 | // @ts-ignore
11 | const EXPLORER_URL_FORMAT =
12 | process.env.REACT_APP_EXPLORER_URL || "https://librabrowser.io/version/{version}";
13 |
14 | interface ExplorerLinkProps {
15 | blockchainTx: BlockchainTransaction;
16 | }
17 |
18 | function ExplorerLink({ blockchainTx }: ExplorerLinkProps) {
19 | const blockExplorerUrl = EXPLORER_URL_FORMAT.replace(
20 | "{version}",
21 | blockchainTx.version.toString()
22 | );
23 | return (
24 | >
25 | {({ theme }) => (
26 | Linking.openURL(blockExplorerUrl)}>
27 | {blockchainTx.version}
28 |
29 | )}
30 |
31 | );
32 | }
33 |
34 | export default ExplorerLink;
35 |
--------------------------------------------------------------------------------
/mobile/src/components/InputErrorMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Text, ThemeConsumer } from "react-native-elements";
6 | import { appTheme } from "../styles";
7 |
8 | interface InputErrorMessageProps {
9 | message: string;
10 | }
11 |
12 | function InputErrorMessage({ message }: InputErrorMessageProps) {
13 | return (
14 | >
15 | {({ theme }) => {message}}
16 |
17 | );
18 | }
19 |
20 | export default InputErrorMessage;
21 |
--------------------------------------------------------------------------------
/mobile/src/components/LegalDisclaimer.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Text } from "react-native-elements";
6 | import { View } from "react-native";
7 | import { useTranslation } from "react-i18next";
8 |
9 | function LegalDisclaimer() {
10 | const { t } = useTranslation("legal");
11 |
12 | return (
13 |
21 | {t("legal_disclaimer")}
22 |
23 | );
24 | }
25 |
26 | export default LegalDisclaimer;
27 |
--------------------------------------------------------------------------------
/mobile/src/components/Messages/ErrorMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Text, View } from "react-native";
6 | import { appTheme } from "../../styles";
7 | import { ThemeConsumer } from "react-native-elements";
8 |
9 | interface ErrorMessageProps {
10 | message: string;
11 | }
12 |
13 | function ErrorMessage({ message }: ErrorMessageProps) {
14 | return (
15 | >
16 | {({ theme }) => (
17 |
18 | {message}
19 |
20 | )}
21 |
22 | );
23 | }
24 |
25 | export default ErrorMessage;
26 |
--------------------------------------------------------------------------------
/mobile/src/components/Messages/InfoMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Text, View } from "react-native";
6 | import { appTheme } from "../../styles";
7 | import { ThemeConsumer } from "react-native-elements";
8 |
9 | interface InfoMessageProps {
10 | message: string;
11 | }
12 |
13 | function InfoMessage({ message }: InfoMessageProps) {
14 | return (
15 | >
16 | {({ theme }) => (
17 |
18 | {message}
19 |
20 | )}
21 |
22 | );
23 | }
24 |
25 | export default InfoMessage;
26 |
--------------------------------------------------------------------------------
/mobile/src/components/NetworkIndicator.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { View } from "react-native";
6 | import { Text } from "react-native-elements";
7 | // @ts-ignore
8 | import BackArrow from "../assets/back-arrow.svg";
9 |
10 | interface NetworkIndicatorProps {
11 | showBack: boolean;
12 | onBackPress: () => void;
13 | }
14 |
15 | const NetworkIndicator = ({ showBack, onBackPress }: NetworkIndicatorProps) => (
16 |
17 | {showBack && }
18 |
19 | Running on Testnet
20 |
21 |
22 | );
23 |
24 | export default NetworkIndicator;
25 |
--------------------------------------------------------------------------------
/mobile/src/components/TestnetWarning.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { StyleSheet, View } from "react-native";
6 | import { Text, ThemeConsumer } from "react-native-elements";
7 | import { useTranslation } from "react-i18next";
8 | import { appTheme } from "../styles";
9 |
10 | function TestnetWarning() {
11 | const { t } = useTranslation("legal");
12 |
13 | return (
14 | >
15 | {({ theme }) => (
16 |
17 | {t("testnet_warning")}
18 |
19 | )}
20 |
21 | );
22 | }
23 |
24 | export default TestnetWarning;
25 |
--------------------------------------------------------------------------------
/mobile/src/components/VerifyingMessage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import React from "react";
5 | import { Text, ThemeConsumer } from "react-native-elements";
6 | import { useTranslation } from "react-i18next";
7 | import { appTheme } from "../styles";
8 | import {View} from "react-native";
9 |
10 | function VerifyingMessage() {
11 | const { t } = useTranslation("layout");
12 |
13 | return (
14 | >
15 | {({ theme }) => (
16 |
17 | {t("verification_pending.title")}
18 | {t("verification_pending.description")}
19 |
20 | )}
21 |
22 | );
23 | }
24 |
25 | export default VerifyingMessage;
26 |
--------------------------------------------------------------------------------
/mobile/src/currencies.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FiatCurrenciesSettings, DiemCurrenciesSettings } from "./interfaces/currencies";
5 |
6 | export const diemCurrencies: DiemCurrenciesSettings = {
7 | XDM: {
8 | name: "Diem",
9 | symbol: "XDM",
10 | sign: "≋XDM",
11 | },
12 | XUS: {
13 | name: "XUS",
14 | symbol: "XUS",
15 | sign: "≋XUS",
16 | },
17 | Coin2: {
18 | name: "Coin2",
19 | symbol: "Coin2",
20 | sign: "≋Coin2",
21 | },
22 | };
23 |
24 | export const fiatCurrencies: FiatCurrenciesSettings = {
25 | USD: {
26 | symbol: "USD",
27 | sign: "$",
28 | },
29 | EUR: {
30 | symbol: "EUR",
31 | sign: "€",
32 | },
33 | GBP: {
34 | symbol: "GBP",
35 | sign: "£",
36 | },
37 | CHF: {
38 | symbol: "CHF",
39 | sign: "Fr",
40 | },
41 | CAD: {
42 | symbol: "CAD",
43 | sign: "$",
44 | },
45 | AUD: {
46 | symbol: "AUD",
47 | sign: "$",
48 | },
49 | NZD: {
50 | symbol: "NZD",
51 | sign: "$",
52 | },
53 | JPY: {
54 | symbol: "JPY",
55 | sign: "¥",
56 | },
57 | };
58 |
--------------------------------------------------------------------------------
/mobile/src/i18n.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import i18next from "i18next";
5 | import { initReactI18next } from "react-i18next";
6 | import LocaleResources from "./locales";
7 |
8 | i18next.use(initReactI18next).init({
9 | interpolation: { escapeValue: false }, // React already does escaping,
10 | lng: "en",
11 | debug: true,
12 | resources: LocaleResources,
13 | });
14 |
15 | export const Languages = Object.keys(LocaleResources);
16 |
17 | export default i18next;
18 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/account.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DiemCurrency } from "./currencies";
5 |
6 | export interface DiemCurrencyBalance {
7 | currency: DiemCurrency;
8 | balance: number;
9 | }
10 |
11 | export interface Account {
12 | balances: DiemCurrencyBalance[];
13 | }
14 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/blockchain.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export interface BlockchainTransaction {
5 | version: number;
6 | status: string;
7 | expirationTime: string;
8 | source: string;
9 | destination: string;
10 | amount: number;
11 | sequenceNumber: number;
12 | }
13 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/cico.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export type QuoteAction = "buy" | "sell";
5 |
6 | export interface RequestForQuote {
7 | action: QuoteAction;
8 | amount: number;
9 | currency_pair: string; // FIXME: specify the supported values
10 | }
11 |
12 | export interface Quote {
13 | quoteId: string;
14 | rfq: RequestForQuote;
15 | price: number;
16 | expirationTime: Date;
17 | }
18 |
19 | export interface Rate {
20 | currency_pair: string;
21 | price: number;
22 | }
23 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/currencies.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export type DiemCurrency = "XDM" | "XUS" | "Coin2";
5 |
6 | export type FiatCurrency = "USD" | "EUR" | "GBP" | "CHF" | "CAD" | "AUD" | "NZD" | "JPY";
7 |
8 | export type DiemCurrenciesSettings = {
9 | [key in DiemCurrency]: {
10 | name: string;
11 | symbol: DiemCurrency;
12 | sign: string;
13 | };
14 | };
15 |
16 | export type FiatCurrenciesSettings = {
17 | [key in FiatCurrency]: {
18 | symbol: FiatCurrency;
19 | sign: string;
20 | };
21 | };
22 |
23 | export type Rates = {
24 | [key in DiemCurrency]: {
25 | [key in FiatCurrency | DiemCurrency]: number;
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/transaction.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DiemCurrency } from "./currencies";
5 | import { BlockchainTransaction } from "./blockchain";
6 |
7 | export interface VASPAccount {
8 | vasp_name: string;
9 | user_id: string;
10 | full_addr: string;
11 | }
12 |
13 | export type TransactionDirection = "received" | "sent";
14 |
15 | export type TransactionStatus = "completed" | "pending" | "canceled";
16 |
17 | export interface Transaction {
18 | id: string;
19 | direction: TransactionDirection;
20 | status: TransactionStatus;
21 | currency: DiemCurrency;
22 | source: VASPAccount;
23 | destination: VASPAccount;
24 | amount: number;
25 | blockchain_tx?: BlockchainTransaction;
26 | timestamp: string;
27 | is_internal: boolean;
28 | }
29 |
--------------------------------------------------------------------------------
/mobile/src/interfaces/user.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Moment } from "moment";
5 | import { FiatCurrency } from "./currencies";
6 |
7 | export enum RegistrationStatus {
8 | Registered = "Registered",
9 | Verified = "Verified",
10 | Pending = "Pending",
11 | Approved = "Approved",
12 | Rejected = "Rejected",
13 | }
14 |
15 | export type PaymentMethodProviders = "BankAccount" | "CreditCard";
16 |
17 | export const paymentMethodsLabels: { [key in PaymentMethodProviders]: string } = {
18 | BankAccount: "Bank Account",
19 | CreditCard: "Credit Card",
20 | };
21 |
22 | export interface PaymentMethod {
23 | id: number;
24 | name: string;
25 | provider: PaymentMethodProviders;
26 | token: string;
27 | }
28 |
29 | export type NewPaymentMethod = Pick;
30 |
31 | export interface UserInfo {
32 | selected_fiat_currency: FiatCurrency;
33 | selected_language: string;
34 | first_name: string;
35 | last_name: string;
36 | dob: Moment | string;
37 | phone: string;
38 | country?: string;
39 | address_1: string;
40 | address_2: string;
41 | city: string;
42 | state: string;
43 | zip: string;
44 | }
45 |
46 | export interface User extends UserInfo {
47 | username: string;
48 | is_admin: boolean;
49 | registration_status: RegistrationStatus;
50 | paymentMethods?: PaymentMethod[];
51 | }
52 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import Layout from "./layout.json";
5 | import Auth from "./auth.json";
6 | import Verify from "./verify.json";
7 | import Transaction from "./transaction.json";
8 | import Transfer from "./transfer.json";
9 | import Send from "./send.json";
10 | import Receive from "./receive.json";
11 | import Validations from "./validations.json";
12 | import Settings from "./settings.json";
13 | import Legal from "./legal.json";
14 |
15 | export default {
16 | layout: Layout,
17 | auth: Auth,
18 | verify: Verify,
19 | transaction: Transaction,
20 | send: Send,
21 | receive: Receive,
22 | transfer: Transfer,
23 | validations: Validations,
24 | settings: Settings,
25 | legal: Legal,
26 | };
27 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Diem Wallet",
3 | "total_balance": "Total Balance",
4 | "balances": "Your Balances",
5 | "transactions": "Latest Transactions",
6 | "transactions_empty": "You don’t have any transactions yet. Once you send, request or transfer money, the transactions will appear here.",
7 | "all_transactions": "All Transactions",
8 | "all_transactions_link": "See All",
9 | "all_currencies": "All Currencies",
10 | "all_sorts": "All Sorts",
11 | "price": "Currently equal to",
12 | "close": "Close",
13 | "actions": {
14 | "send": "Send",
15 | "request": "Request",
16 | "transfer": "Transfer",
17 | "settings": "Settings"
18 | },
19 | "verification_pending": {
20 | "title": "Verification Pending",
21 | "description": "Your information is being reviewed. We’ll let you know when it’s complete."
22 | },
23 | "feedback": {
24 | "title": "Leave your feedback",
25 | "text": "Feedback"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/legal.json:
--------------------------------------------------------------------------------
1 | {
2 | "legal_disclaimer": "This is a demonstration wallet with no actual users. Do not use any username and/or password you use for other services. Create a test account instead. The compliance processes depicted in this demo wallet are for demonstration purposes only and do not reflect the specific compliance obligations of VASPs under applicable regulatory frameworks, their compliance programs, and/or standards imposed by Diem Networks.",
3 | "example_section_warning": "Example section. No real data required",
4 | "testnet_warning": "This demonstration wallet does not use real money"
5 | }
--------------------------------------------------------------------------------
/mobile/src/locales/en/receive.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "headline": "Select Digital Currency",
4 | "currency_label": "Each one of your digital currencies has a different address.",
5 | "currency": "Currency",
6 | "scan_qr": "Scan QR",
7 | "text": "You can copy your unique address and give it to the person you’d like to receive money from. Or others can read the address by scanning the QR code.",
8 | "copy": "Copy Address",
9 | "copied": "Copied <1 />"
10 | }
11 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/send.json:
--------------------------------------------------------------------------------
1 | {
2 | "success_message": "Your transaction is on the way!",
3 | "fail_message": "Failed to send transaction",
4 | "form": {
5 | "title": "Send Money",
6 | "diemCurrency": "currency",
7 | "diemCurrency_placeholder": "Select a currency",
8 | "fiatCurrency": "fiat currency",
9 | "amount": "Amount",
10 | "price": "currently equal to",
11 | "address": "recipient",
12 | "address_placeholder": "Enter an address",
13 | "exchange_rate": "Exchange rate",
14 | "review": "Review"
15 | },
16 | "review": {
17 | "title": "Review Transaction",
18 | "description": "Please review your transaction. Once you send money, the transaction can’t be reversed.",
19 | "amount": "You’re sending",
20 | "price": "Currently equal to",
21 | "exchange_rate": "Exchange rate",
22 | "address": "To",
23 | "confirm": "Send",
24 | "done": "Done",
25 | "back": "Back"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Settings",
3 | "success_message": "Settings saved successfully!",
4 | "payment_methods": {
5 | "title": "Payment Methods",
6 | "credit_cards": {
7 | "title": "Credit Cards",
8 | "not_found": "You haven't added a credit card yet",
9 | "add": "Add New",
10 | "form": {
11 | "title": "Add Credit Card",
12 | "number": "Card number",
13 | "name": "Name",
14 | "expiry": "Valid Thru",
15 | "cvc": "CVC",
16 | "submit": "Add New Credit Card"
17 | }
18 | },
19 | "bank_accounts": {
20 | "title": "Bank Accounts",
21 | "not_found": "You haven't added a bank account yet",
22 | "add": "Add New",
23 | "form": {
24 | "title": "Add Bank Account",
25 | "account_number": "Account Number",
26 | "bank": "Bank",
27 | "name": "Name",
28 | "submit": "Add New Bank Account"
29 | }
30 | }
31 | },
32 | "preferences": {
33 | "general": {
34 | "title": "General",
35 | "email": "Your email"
36 | },
37 | "form": {
38 | "title": "Preferences",
39 | "fiat_currency": "Local currency",
40 | "language": "Language",
41 | "submit": "Save Settings"
42 | }
43 | },
44 | "signout": "Logout"
45 | }
--------------------------------------------------------------------------------
/mobile/src/locales/en/transaction.json:
--------------------------------------------------------------------------------
1 | {
2 | "sent": "Sent",
3 | "received": "Received",
4 | "price": "Currently equal to",
5 | "date": "Date",
6 | "to": "to",
7 | "from": "from",
8 | "sent_to": "Sent to",
9 | "sent_from": "Sent from",
10 | "status": "Status",
11 | "tx_id": "Diem Transaction ID",
12 | "internal": "Internal",
13 | "not_available": "Not available"
14 | }
15 |
--------------------------------------------------------------------------------
/mobile/src/locales/en/validations.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": "Please enter {{field}}",
3 | "min": "Please enter {{field}} above {{min}}",
4 | "max": "Please enter {{field}} below {{max}}",
5 | "minLength": "Please enter {{field}} longer than {{minLength}}",
6 | "maxLength": "Please enter {{field}} shorter than {{maxLength}}",
7 | "pattern": "Please enter valid {{field}}",
8 | "numbersOnly": "Please enter {{field}} with numbers only",
9 | "validDate": "Please enter a valid date",
10 | "pastDateOnly": "Please enter a date in the past",
11 | "noEqualCurrencies": "Please select different currencies",
12 | "noMoreThanBalance": "Please enter {{field}} less than your current {{currency}} balance"
13 | }
14 |
--------------------------------------------------------------------------------
/mobile/src/locales/es/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import Layout from "./layout.json";
5 | import Auth from "./auth.json";
6 | import Verify from "./verify.json";
7 | import Transaction from "./transaction.json";
8 | import Transfer from "./transfer.json";
9 | import Send from "./send.json";
10 | import Receive from "./receive.json";
11 | import Validations from "./validations.json";
12 | import Settings from "./settings.json";
13 |
14 | export default {
15 | layout: Layout,
16 | auth: Auth,
17 | verify: Verify,
18 | transaction: Transaction,
19 | send: Send,
20 | receive: Receive,
21 | transfer: Transfer,
22 | validations: Validations,
23 | settings: Settings,
24 | };
25 |
--------------------------------------------------------------------------------
/mobile/src/locales/es/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cartera Diem",
3 | "total_balance": "Saldo Total",
4 | "balances": "Ver sus saldos",
5 | "transactions": "'Últimas transacciones'",
6 | "transactions_empty": "Aún no tienes ninguna transacción. Una vez que envíe, solicite o transfiera dinero, las transacciones aparecerán aquí.",
7 | "all_transactions": "Todas las Transacciones",
8 | "all_transactions_link": "Ver todo",
9 | "all_currencies": "Todas las monedas",
10 | "all_sorts": "Todo tipo",
11 | "price": "Actualmente igual a",
12 | "close": "Cerrar",
13 | "actions": {
14 | "send": "Enviar",
15 | "request": "Solicitud",
16 | "transfer": "Transferir",
17 | "settings": "Configuración"
18 | },
19 | "verification_pending": {
20 | "title": "Verificación pendiente",
21 | "description": "Su información está siendo revisada. Te avisaremos cuando esté completo."
22 | },
23 | "feedback": {
24 | "title": "Deje sus comentarios",
25 | "text": "Comentarios"
26 | }
27 | }
--------------------------------------------------------------------------------
/mobile/src/locales/es/receive.json:
--------------------------------------------------------------------------------
1 | {
2 | "headline": "Seleccionar moneda digital",
3 | "currency_label": "Cada una de sus monedas digitales tiene una dirección diferente.",
4 | "currency": "Divisa",
5 | "scan_qr": "Escanea el código QR",
6 | "text": "Puede copiar su dirección única y dársela a la persona de la que desea recibir dinero. O otros pueden leer la dirección escaneando el código QR.",
7 | "copy": "Copiar dirección",
8 | "copied": "Copiado <1 />"
9 | }
--------------------------------------------------------------------------------
/mobile/src/locales/es/send.json:
--------------------------------------------------------------------------------
1 | {
2 | "success_message": "Su transacción está en camino!",
3 | "fail_message": "Error al enviar la transacción",
4 | "form": {
5 | "title": "Enviar Dinero a Usuario",
6 | "diemCurrency": "moneda",
7 | "diemCurrency_placeholder": "Selecciona una moneda",
8 | "fiatCurrency": "Moneda Fiat",
9 | "amount": "Cantidad",
10 | "price": "actualmente igual a",
11 | "address": "destinatario",
12 | "address_placeholder": "Ingresar Dirección",
13 | "exchange_rate": "Tipo de cambio",
14 | "review": "Revisión"
15 | },
16 | "review": {
17 | "title": "Revisar transacción",
18 | "description": "Por favor revise su transacción. Una vez que envía dinero, la transacción no se puede revertir.",
19 | "amount": "Estas enviando",
20 | "price": "Actualmente igual a",
21 | "exchange_rate": "Tipo de cambio",
22 | "address": "Para",
23 | "confirm": "Enviar",
24 | "done": "Listo",
25 | "back": "Volver"
26 | }
27 | }
--------------------------------------------------------------------------------
/mobile/src/locales/es/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Configuración",
3 | "success_message": "Ajustes guardados correctamente!",
4 | "payment_methods": {
5 | "title": "Formas de pago",
6 | "credit_cards": {
7 | "title": "Tarjetas de Crédito",
8 | "not_found": "Aún no ha agregado una tarjeta de crédito",
9 | "add": "Añadir nueva",
10 | "form": {
11 | "title": "Añadir una tarjeta de crédito",
12 | "number": "Número de la tarjeta",
13 | "name": "Nombre",
14 | "expiry": "Válida hasta",
15 | "cvc": "CVC",
16 | "submit": "Añadir nueva tarjeta de crédito"
17 | }
18 | },
19 | "bank_accounts": {
20 | "title": "Cuentas Bancarias",
21 | "not_found": "Aún no ha agregado una cuenta bancaria",
22 | "add": "Añadir nueva",
23 | "form": {
24 | "title": "Añadir cuenta bancaria",
25 | "account_number": "Numero de Tarjeta de Banco",
26 | "bank": "Banco",
27 | "name": "Nombre",
28 | "submit": "Nueva cuenta bancaria"
29 | }
30 | }
31 | },
32 | "preferences": {
33 | "general": {
34 | "title": "General",
35 | "email": "Su correo electrónico"
36 | },
37 | "form": {
38 | "title": "Preferencias",
39 | "fiat_currency": "Moneda local",
40 | "language": "Idioma",
41 | "submit": "Salvar configuración"
42 | }
43 | },
44 | "signout": "Cerrar Sesión"
45 | }
--------------------------------------------------------------------------------
/mobile/src/locales/es/transaction.json:
--------------------------------------------------------------------------------
1 | {
2 | "sent": "Enviado",
3 | "received": "Recibido",
4 | "price": "Actualmente igual a",
5 | "date": "Fecha",
6 | "to": "a",
7 | "from": "desde",
8 | "sent_to": "Enviar a",
9 | "sent_from": "Enviado desde",
10 | "status": "Estatus",
11 | "tx_id": "ID de transacción de Diem",
12 | "internal": "Interna",
13 | "not_available": "No disponible"
14 | }
--------------------------------------------------------------------------------
/mobile/src/locales/es/validations.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": "Por favor, complete el campo:",
3 | "min": "Ingrese {{field}} arriba {{min}}",
4 | "max": "Ingrese {{field}} debajo de {{max}}",
5 | "minLength": "Ingrese {{field}} más de {{minLength}}",
6 | "maxLength": "Ingrese {{field}} más corto que {{maxLength}}",
7 | "pattern": "Introduzca el campo válido",
8 | "numbersOnly": "Ingrese {{field}} solo con números",
9 | "validDate": "Por favor, introduzca una fecha válida",
10 | "pastDateOnly": "Por favor introduce una fecha de inicio en el pasado.",
11 | "noEqualCurrencies": "Por favor seleccione diferentes monedas",
12 | "noMoreThanBalance": "Ingrese {{field}} menos que su saldo actual de {{currency}}"
13 | }
--------------------------------------------------------------------------------
/mobile/src/locales/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Resource } from "i18next";
5 | import EN from "./en";
6 | import ES from "./es";
7 |
8 | export default {
9 | en: EN,
10 | es: ES,
11 | } as Resource;
12 |
--------------------------------------------------------------------------------
/mobile/src/screens/VerifySteps/interfaces.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { Moment } from "moment";
5 | import { FiatCurrency } from "../../interfaces/currencies";
6 |
7 | export interface IdentityInfo extends Record {
8 | first_name: string;
9 | last_name: string;
10 | dob: string | Moment;
11 | phone_prefix: string;
12 | phone_number: string;
13 | }
14 |
15 | export interface CountryInfo extends Record {
16 | country: string;
17 | }
18 |
19 | export interface AddressInfo extends Record {
20 | address_1: string;
21 | address_2: string;
22 | city: string;
23 | state: string;
24 | zip: string;
25 | }
26 |
27 | export interface DefaultSettings extends Record {
28 | default_fiat_currency: FiatCurrency;
29 | }
30 |
--------------------------------------------------------------------------------
/mobile/src/services/errors.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export interface ErrorMessage {
5 | error: string;
6 | code: number;
7 | }
8 |
9 | export class BackendError extends Error {
10 | constructor(message: string, public httpStatus: number) {
11 | super(message);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/mobile/src/services/sessionStorage.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import AsyncStorage from "@react-native-community/async-storage";
5 |
6 | class SessionStorage {
7 | async storeAccessToken(token: string): Promise {
8 | await AsyncStorage.setItem("token", token);
9 | }
10 |
11 | async getAccessToken(): Promise {
12 | const token = await AsyncStorage.getItem("token");
13 | if (!token) {
14 | return undefined;
15 | }
16 | return token;
17 | }
18 |
19 | async removeAccessToken(): Promise {
20 | await AsyncStorage.removeItem("token");
21 | }
22 | }
23 |
24 | export default new SessionStorage();
25 |
--------------------------------------------------------------------------------
/mobile/src/utils/shorten-address.ts:
--------------------------------------------------------------------------------
1 | // Copyright (c) The Diem Core Contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export function shortenDiemAddress(address: string): string {
5 | const len = 6;
6 | return address.substr(0, len) + "...." + address.substr(len * -1);
7 | }
8 |
--------------------------------------------------------------------------------
/scripts/compile_frontend.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | script_dir="$(dirname "$0")"
7 | project_dir="$(dirname "$script_dir")"
8 |
9 | docker build -t reference-wallet-frontend-build -f "${project_dir}/frontend/Dockerfile" "${project_dir}/frontend/"
10 |
--------------------------------------------------------------------------------
/scripts/funcs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | NC='\033[0m'
7 | RED='\033[0;31m'
8 | GREEN='\033[0;32m'
9 | PINK='\033[1;35m'
10 | YELLOW='\033[0;33m'
11 |
12 | ##
13 | # More consistent echo.
14 | #
15 | ec() {
16 | IFS=' ' printf "%b\n" "$*"
17 | }
18 |
19 | ##
20 | # Outputs new line.
21 | # No parameters.
22 | #
23 | br() {
24 | ec ''
25 | }
26 |
27 | success() {
28 | ec "${GREEN}$1${NC}"
29 | }
30 |
31 | info() {
32 | ec "${PINK}$1${NC}"
33 | }
34 |
35 | warn() {
36 | ec "${YELLOW}$1${NC}"
37 | }
38 |
39 | error() {
40 | >&2 ec "${RED}ERROR: $1${NC}"
41 | }
42 |
43 | fail() {
44 | error "$@"
45 | exit 1
46 | }
47 |
--------------------------------------------------------------------------------
/scripts/install-git-hooks.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 |
7 | # This is the list of existing hook scripts
8 | # All the hook scripts must be inside scripts directory
9 | hooks=pre-commit
10 |
11 | a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}
12 | scripts_dir=$(cd "$a"; pwd)
13 |
14 | get_path="git rev-parse --git-path hooks"
15 |
16 | for hook in "${hooks}"; do
17 | echo Installing ${hook}
18 | cp ${scripts_dir}/${hook} $(${get_path})/${hook} || exit 1
19 | done
20 |
21 | echo Done.
22 |
23 |
--------------------------------------------------------------------------------
/scripts/wait_for_server_ready.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | set -euo pipefail
7 |
8 | service_num=$1
9 |
10 | for attempt in {1..60} ; do
11 | logs=$(docker ps -a | awk '{ print $1 }' | awk 'NR>1' | xargs -L1 -I {} sh -c "docker logs {} 2>&1 | tail -1")
12 | lines=$(echo "$logs"| wc -l)
13 | echo "tail logs lines: $lines, expect: $service_num"
14 | unreachable=$(echo "$logs"| grep unreachable || true)
15 | echo "unreachable: $unreachable"
16 | if [ $lines -ge $service_num ]; then
17 | if [ -z "$unreachable" ]; then
18 | echo "All services reachable"
19 | exit 0
20 | fi
21 | fi
22 |
23 | echo "Attempt $attempt, some services still unreachable"
24 | sleep 3
25 | done
26 | echo "Services unhealthy"
27 | exit 1
28 |
--------------------------------------------------------------------------------
/vasp-validator/.env.example:
--------------------------------------------------------------------------------
1 | VALIDATOR_URL=http://localhost:45461/api
2 | TESTEE_URL=http://localhost:48163/api
3 |
--------------------------------------------------------------------------------
/vasp-validator/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length = 88
3 | extend-ignore = E203
4 |
--------------------------------------------------------------------------------
/vasp-validator/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | name = "pypi"
3 | url = "https://pypi.org/simple"
4 | verify_ssl = true
5 |
6 | [dev-packages]
7 | diem-vasp-validator = {editable = true, path = "."}
8 | diem = {editable = true, git = "https://github.com/firstdag/client-sdk-python.git", ref = "dip-8"}
9 | flake8 = "*"
10 | black = "*"
11 |
12 | [packages]
13 |
14 | [requires]
15 | python_version = "3.7"
16 |
17 | [pipenv]
18 | allow_prereleases = true
19 |
--------------------------------------------------------------------------------
/vasp-validator/lint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright (c) The Diem Core Contributors
5 | # SPDX-License-Identifier: Apache-2.0
6 | #
7 |
8 | echo "> Running Black"
9 | pipenv run black src tests
10 | echo
11 |
12 | echo "> Running flake8"
13 | pipenv run flake8 src tests
14 |
--------------------------------------------------------------------------------
/vasp-validator/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | log_cli_level = INFO
3 | log_format = %(levelname)-7s [%(name)s] %(message)s
4 |
--------------------------------------------------------------------------------
/vasp-validator/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import os
5 |
6 | from setuptools import setup
7 |
8 | this_directory = os.path.abspath(os.path.dirname(__file__))
9 | with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
10 | long_description = f.read()
11 |
12 | setup(
13 | name="diem-vasp-validator",
14 | version="1.0.0",
15 | description="Diem VASP validation library",
16 | long_description=long_description,
17 | long_description_content_type="text/markdown",
18 | license="Apache-2.0",
19 | url="https://github.com/diem/reference-wallet",
20 | package_dir={"": "src"},
21 | packages=["vasp_validator"],
22 | install_requires=[
23 | "diem>=1.1.0,<2.0.0",
24 | "dataclasses_json",
25 | "requests",
26 | "pytest",
27 | ],
28 | entry_points={
29 | "console_scripts": [
30 | "validate-vasp = vasp_validator.tests:automatic_validation_main",
31 | ],
32 | },
33 | python_requires=">=3.7",
34 | )
35 |
--------------------------------------------------------------------------------
/vasp-validator/src/vasp_validator/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from .validator_client import ValidatorClient
5 |
6 | __all__ = [
7 | ValidatorClient,
8 | ]
9 |
--------------------------------------------------------------------------------
/vasp-validator/src/vasp_validator/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import argparse
5 | import pytest
6 |
7 |
8 | def parse_args():
9 | parser = argparse.ArgumentParser()
10 | parser.add_argument(
11 | "vasp_proxy_module",
12 | help="Module path containing vasp_proxy_class",
13 | )
14 | parser.add_argument(
15 | "vasp_proxy_class",
16 | help="Instances of this class will be used to communicate with the tested VASP",
17 | )
18 | return parser.parse_args()
19 |
20 |
21 | def automatic_validation_main():
22 | args = parse_args()
23 | pytest.main(
24 | [
25 | "-p",
26 | "vasp_validator.tests.plugin",
27 | "--pyargs",
28 | "vasp_validator.tests.test_send_tx",
29 | "--vasp-proxy-module",
30 | args.vasp_proxy_module,
31 | "--vasp-proxy-class",
32 | args.vasp_proxy_class,
33 | ]
34 | )
35 |
--------------------------------------------------------------------------------
/vasp-validator/src/vasp_validator/tests/plugin.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from . import vasp_proxy_hook
5 |
6 |
7 | def pytest_addoption(parser, pluginmanager):
8 | parser.addoption(
9 | "--vasp-proxy-module",
10 | dest="vasp_proxy_module",
11 | help="Module path containing vasp-proxy-class",
12 | )
13 | parser.addoption(
14 | "--vasp-proxy-class",
15 | dest="vasp_proxy_class",
16 | help="Instances of this class will be used to communicate with the tested VASP",
17 | )
18 |
19 |
20 | def pytest_addhooks(pluginmanager):
21 | pluginmanager.add_hookspecs(vasp_proxy_hook)
22 |
--------------------------------------------------------------------------------
/vasp-validator/src/vasp_validator/tests/vasp_proxy_hook.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from pytest import hookspec
5 |
6 | from ..vasp_proxy import VaspProxy
7 |
8 |
9 | @hookspec(firstresult=True)
10 | def pytest_create_vasp_proxy() -> VaspProxy:
11 | """
12 | Controls which testee VASP object will be used during the tests
13 | """
14 |
--------------------------------------------------------------------------------
/vasp-validator/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright (c) The Diem Core Contributors
5 | # SPDX-License-Identifier: Apache-2.0
6 | #
7 |
8 | # If first argument is not a flag, it's a subtest selector
9 | if [ -n "${1}" ] && [ "${1#-}" = "${1}" ]; then
10 | subtests=$1
11 | shift
12 | fi
13 |
14 | tests_selector=vasp_validator.tests${subtests:+.}${subtests}
15 | pipenv run pytest -r A -p vasp_validator.tests.plugin --pyargs ${tests_selector} "$@" ./tests
16 |
--------------------------------------------------------------------------------
/vasp-validator/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
--------------------------------------------------------------------------------
/vasp-validator/tests/conftest.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import os
5 |
6 | from vasp_validator.vasp_proxy import VaspProxy
7 | from .vasp_proxy_testee import VaspProxyTestee
8 |
9 | TESTEE_URL = os.environ["TESTEE_URL"]
10 |
11 |
12 | def pytest_create_vasp_proxy() -> VaspProxy:
13 | """
14 | This is a hook function used by vasp_validator plugin.
15 | If defined, it will be called to created instances of the VASP proxy object.
16 | """
17 | return VaspProxyTestee(TESTEE_URL)
18 |
--------------------------------------------------------------------------------
/vasp-validator/tests/test_vasp_proxy_hook.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The Diem Core Contributors
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | def test_tautology():
6 | ...
7 |
--------------------------------------------------------------------------------
/wait.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (c) The Diem Core Contributors
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | HOST=$1
7 | PORT=$2
8 |
9 | if [ -z $HOST ] || [ -z $PORT ]; then
10 | echo "Missing HOST or PORT"
11 | exit 1
12 | fi
13 |
14 | for attempt in {1..60} ; do
15 | nc -z $HOST $PORT && echo "Ping successful!" && exit 0 || sleep 3
16 | echo "Attempt $attempt: $HOST:$PORT unreachable, sleeping..."
17 | done
18 | echo "ERROR: timed out"
19 | exit 1
20 |
--------------------------------------------------------------------------------