├── frontend ├── CNAME ├── public │ ├── CNAME │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── themes │ │ ├── images.ts │ │ ├── darkTheme │ │ │ ├── index.ts │ │ │ └── images.ts │ │ ├── lightTheme │ │ │ ├── index.ts │ │ │ └── images.ts │ │ ├── index.ts │ │ ├── rem.ts │ │ └── ThemeProvider.tsx │ ├── components │ │ ├── Dialog │ │ │ ├── index.tsx │ │ │ ├── Dialog.tsx │ │ │ ├── styles.css │ │ │ └── SuccessNft.tsx │ │ ├── Header │ │ │ ├── index.tsx │ │ │ └── DarkMode.tsx │ │ ├── Wallet │ │ │ ├── index.tsx │ │ │ ├── Wallet.tsx │ │ │ ├── LoginType.tsx │ │ │ └── LoginModal.tsx │ │ ├── Tooltip │ │ │ ├── index.tsx │ │ │ └── Tooltip.tsx │ │ ├── Scrollbar │ │ │ ├── index.ts │ │ │ ├── styles.ts │ │ │ └── Scrollbar.tsx │ │ ├── TokenInput │ │ │ └── index.tsx │ │ ├── Divider.ts │ │ ├── Anchor.tsx │ │ ├── Layout.tsx │ │ ├── Img.tsx │ │ ├── HideElements.ts │ │ ├── SizedBox.tsx │ │ ├── TokenIcon.tsx │ │ ├── Progressbar.tsx │ │ ├── Loading.tsx │ │ ├── TextArea.tsx │ │ ├── Card.tsx │ │ ├── AmountInput.tsx │ │ ├── Flex.ts │ │ ├── Symbol.tsx │ │ ├── LinkGroup.tsx │ │ ├── SwitchButtons.tsx │ │ ├── Button.tsx │ │ ├── Notification.tsx │ │ ├── Text.tsx │ │ ├── Input.tsx │ │ └── Collapse │ │ │ └── types.ts │ ├── screens │ │ ├── Faucet │ │ │ ├── index.tsx │ │ │ └── Faucet.tsx │ │ ├── Tutorial │ │ │ ├── index.tsx │ │ │ └── Tutorial.tsx │ │ ├── Dashboard │ │ │ ├── index.tsx │ │ │ ├── ActionTab │ │ │ │ └── index.tsx │ │ │ ├── SwitchActions.tsx │ │ │ ├── AvailableToBorrow.tsx │ │ │ └── SummaryCard.tsx │ │ ├── Tutorials │ │ │ ├── index.tsx │ │ │ ├── Tutorials.tsx │ │ │ └── TutorialCard.tsx │ │ └── TechnicalWork.tsx │ ├── utils │ │ ├── sleep.ts │ │ ├── toUpperFirstLetter.ts │ │ ├── isRoutesEquals.ts │ │ ├── getWordsFromValue.ts │ │ ├── centerEllipsis.ts │ │ ├── mnemonic.ts │ │ ├── localStorage.ts │ │ ├── indexerUtils.ts │ │ └── getCurrentBrowser.js │ ├── assets │ │ ├── fonts │ │ │ ├── Inter-Bold.ttf │ │ │ ├── Inter-Medium.ttf │ │ │ ├── Inter-Regular.ttf │ │ │ └── Inter-SemiBold.ttf │ │ ├── icons │ │ │ ├── minus.svg │ │ │ ├── minus-dark.svg │ │ │ ├── plus.svg │ │ │ ├── plus-dark.svg │ │ │ ├── arrow.svg │ │ │ ├── arrowDown.svg │ │ │ ├── close.svg │ │ │ ├── darkArrowDown.svg │ │ │ ├── rightArrow.svg │ │ │ ├── rightArrow-dark.svg │ │ │ ├── moon.svg │ │ │ ├── moon-dark.svg │ │ │ ├── information.svg │ │ │ ├── error.svg │ │ │ ├── warning.svg │ │ │ ├── success.svg │ │ │ ├── sun-dark.svg │ │ │ ├── disconnect.svg │ │ │ ├── attention.svg │ │ │ ├── health-gradient.svg │ │ │ ├── health-gradient-small.svg │ │ │ ├── copy.svg │ │ │ ├── whiteLink.svg │ │ │ ├── sun.svg │ │ │ ├── info.svg │ │ │ ├── coins.svg │ │ │ ├── coins-dark.svg │ │ │ ├── key-dark.svg │ │ │ ├── analytics.svg │ │ │ ├── analytics-dark.svg │ │ │ ├── fuelLogo.svg │ │ │ ├── wallet.svg │ │ │ └── wallet-dark.svg │ │ └── tokens │ │ │ ├── BUSD.svg │ │ │ ├── BNB.svg │ │ │ ├── usdt.svg │ │ │ ├── chainlink.svg │ │ │ ├── ethereum.svg │ │ │ ├── sway.svg │ │ │ ├── compound.svg │ │ │ ├── bitcoin.svg │ │ │ └── usdc.svg │ ├── hooks │ │ ├── useIsomorphicLayoutEffect.ts │ │ ├── useVM.ts │ │ ├── useFuel.tsx │ │ ├── useHover.tsx │ │ ├── useOnClickOutside.ts │ │ ├── useIsConnected.tsx │ │ ├── useWindowSize.ts │ │ ├── useElementSize.ts │ │ └── useEventListener.ts │ ├── stores │ │ ├── useStores.ts │ │ ├── index.tsx │ │ ├── RootStore.ts │ │ ├── NotificationStore.ts │ │ └── PricesStore.ts │ ├── contracts │ │ ├── index.ts │ │ ├── common.d.ts │ │ └── OracleAbi.d.ts │ ├── typings │ │ ├── emotion.d.ts │ │ └── react-app-env.d.ts │ ├── constants │ │ ├── tokenLogos.ts │ │ ├── tutorials.ts │ │ ├── tokens.json │ │ └── index.ts │ ├── index.css │ ├── App.tsx │ ├── entities │ │ └── Balance.ts │ └── index.tsx ├── config │ ├── webpack │ │ └── persistentCache │ │ │ └── createEnvironmentHash.js │ ├── jest │ │ ├── cssTransform.js │ │ ├── babelTransform.js │ │ └── fileTransform.js │ └── getHttpsConfig.js ├── .gitignore ├── tsconfig.json ├── scripts │ └── test.js └── README.md ├── docs ├── welcome │ ├── faq │ │ ├── README.md │ │ ├── liquidations.md │ │ ├── supplying-and-earning.md │ │ └── borrowing.md │ └── team.md ├── .gitbook │ └── assets │ │ ├── image.png │ │ ├── image (1).png │ │ ├── image (2).png │ │ └── image (3).png ├── get-started-on-fuel │ ├── top-up-wallet.md │ └── create-wallet.md ├── developers │ └── contract-methods.md ├── SUMMARY.md ├── risks.md ├── README.md └── collateral-and-borrowing.md ├── libraries └── i64 │ ├── .gitignore │ ├── Forc.toml │ └── Forc.lock ├── services ├── liquidator │ ├── .gitignore │ ├── src │ │ └── utils │ │ │ ├── mod.rs │ │ │ ├── oracle_utils.rs │ │ │ ├── print_swaygang_sign.rs │ │ │ └── indexer_utils.rs │ ├── Dockerfile │ └── Cargo.toml ├── oracle │ ├── .gitignore │ ├── src │ │ ├── utils │ │ │ ├── mod.rs │ │ │ ├── oracle_abi_calls.rs │ │ │ └── print_swaygang_sign.rs │ │ └── tokens.json │ ├── Cargo.toml │ └── Dockerfile └── swaylend-indexer │ ├── .cargo │ └── config │ ├── swaylend_indexer.manifest.yaml │ ├── Cargo.toml │ ├── schema │ └── swaylend_indexer.schema.graphql │ └── docker-compose.yaml ├── abi ├── market_abi │ ├── .gitignore │ └── Forc.toml └── oracle_abi │ ├── .gitignore │ ├── Forc.toml │ └── src │ └── main.sw ├── contracts ├── market │ ├── .gitignore │ ├── tests │ │ ├── artefacts │ │ │ ├── oracle │ │ │ │ ├── oracle-storage_slots.json │ │ │ │ └── oracle.bin │ │ │ ├── factory │ │ │ │ ├── token-factory-storage_slots.json │ │ │ │ └── token-factory.bin │ │ │ └── config.json │ │ ├── local_tests │ │ │ ├── functions │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── harness.rs │ │ ├── utils │ │ │ ├── contracts_utils │ │ │ │ └── mod.rs │ │ │ └── number_utils.rs │ │ └── testnet_tests │ │ │ ├── mod.rs │ │ │ ├── get_user_supply_borrow.rs │ │ │ ├── absorb_test.rs │ │ │ ├── availtable_to_borrow_test.rs │ │ │ ├── debug_state.rs │ │ │ └── deploy.rs │ ├── src │ │ ├── events.sw │ │ └── helpers.sw │ ├── Forc.toml │ ├── Cargo.toml │ └── Forc.lock └── oracle │ ├── .gitignore │ ├── .docs │ ├── oracle_diagram.png │ ├── oracle-logo-dark-theme.png │ └── oracle-logo-light-theme.png │ ├── Forc.toml │ ├── Forc.lock │ ├── Cargo.toml │ ├── tests │ └── tokens.json │ └── src │ └── main.sw ├── scripts └── get_account_state │ ├── .gitignore │ ├── Forc.toml │ ├── Forc.lock │ └── src │ └── main.sw ├── .gitignore ├── .gitattributes ├── Forc.toml └── Forc.lock /frontend/CNAME: -------------------------------------------------------------------------------- 1 | app.swaylend.com -------------------------------------------------------------------------------- /docs/welcome/faq/README.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | -------------------------------------------------------------------------------- /frontend/public/CNAME: -------------------------------------------------------------------------------- 1 | app.swaylend.com 2 | -------------------------------------------------------------------------------- /libraries/i64/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | -------------------------------------------------------------------------------- /services/liquidator/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /abi/market_abi/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | -------------------------------------------------------------------------------- /abi/oracle_abi/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | -------------------------------------------------------------------------------- /contracts/market/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | -------------------------------------------------------------------------------- /contracts/oracle/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | .env -------------------------------------------------------------------------------- /frontend/src/themes/images.ts: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /scripts/get_account_state/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | target 3 | -------------------------------------------------------------------------------- /contracts/market/tests/artefacts/oracle/oracle-storage_slots.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /contracts/market/tests/local_tests/functions/mod.rs: -------------------------------------------------------------------------------- 1 | mod pause; 2 | -------------------------------------------------------------------------------- /contracts/market/tests/artefacts/factory/token-factory-storage_slots.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | 3 | .idea 4 | **/.env 5 | **/target 6 | **/.DS_Store 7 | -------------------------------------------------------------------------------- /services/oracle/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .idea 4 | .DS_Store 5 | .env -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Syntax highlighting of sway files as rust 2 | *.sw linguist-language=Rust -------------------------------------------------------------------------------- /services/oracle/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod print_swaygang_sign; 2 | pub mod oracle_abi_calls; -------------------------------------------------------------------------------- /services/swaylend-indexer/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-unknown-unknown" 3 | -------------------------------------------------------------------------------- /Forc.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "contracts/market", 4 | "contracts/oracle", 5 | ] -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/src/components/Dialog/index.tsx: -------------------------------------------------------------------------------- 1 | import Dialog from "./Dialog"; 2 | 3 | export default Dialog; 4 | -------------------------------------------------------------------------------- /frontend/src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import Header from "./Header"; 2 | 3 | export default Header; 4 | -------------------------------------------------------------------------------- /frontend/src/components/Wallet/index.tsx: -------------------------------------------------------------------------------- 1 | import Wallet from "./Wallet"; 2 | 3 | export default Wallet; 4 | -------------------------------------------------------------------------------- /frontend/src/screens/Faucet/index.tsx: -------------------------------------------------------------------------------- 1 | import Faucet from "./Faucet"; 2 | 3 | export default Faucet; 4 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/public/logo192.png -------------------------------------------------------------------------------- /frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/public/logo512.png -------------------------------------------------------------------------------- /frontend/src/components/Tooltip/index.tsx: -------------------------------------------------------------------------------- 1 | import Tooltip from "./Tooltip"; 2 | 3 | export default Tooltip; 4 | -------------------------------------------------------------------------------- /frontend/src/screens/Tutorial/index.tsx: -------------------------------------------------------------------------------- 1 | import Tutorial from "./Tutorial"; 2 | 3 | export default Tutorial; 4 | -------------------------------------------------------------------------------- /docs/.gitbook/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/docs/.gitbook/assets/image.png -------------------------------------------------------------------------------- /frontend/src/components/Scrollbar/index.ts: -------------------------------------------------------------------------------- 1 | import Scrollbar from "./Scrollbar"; 2 | 3 | export default Scrollbar; 4 | -------------------------------------------------------------------------------- /frontend/src/screens/Dashboard/index.tsx: -------------------------------------------------------------------------------- 1 | import Dashboard from "./Dashboard"; 2 | 3 | export default Dashboard; 4 | -------------------------------------------------------------------------------- /frontend/src/screens/Tutorials/index.tsx: -------------------------------------------------------------------------------- 1 | import Tutorials from "./Tutorials"; 2 | 3 | export default Tutorials; 4 | -------------------------------------------------------------------------------- /contracts/market/tests/harness.rs: -------------------------------------------------------------------------------- 1 | mod local_tests; 2 | // mod testnet_tests; // todo move to scripts 3 | mod utils; 4 | -------------------------------------------------------------------------------- /contracts/market/tests/local_tests/mod.rs: -------------------------------------------------------------------------------- 1 | mod functions; 2 | mod main_test_uni; 3 | mod main_test_uni_no_debug_mode; 4 | -------------------------------------------------------------------------------- /docs/.gitbook/assets/image (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/docs/.gitbook/assets/image (1).png -------------------------------------------------------------------------------- /docs/.gitbook/assets/image (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/docs/.gitbook/assets/image (2).png -------------------------------------------------------------------------------- /docs/.gitbook/assets/image (3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/docs/.gitbook/assets/image (3).png -------------------------------------------------------------------------------- /frontend/src/components/TokenInput/index.tsx: -------------------------------------------------------------------------------- 1 | import TokenInput from "./TokenInput"; 2 | 3 | export default TokenInput; 4 | -------------------------------------------------------------------------------- /contracts/market/tests/utils/contracts_utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod market_utils; 2 | pub mod oracle_utils; 3 | pub mod token_utils; 4 | -------------------------------------------------------------------------------- /frontend/src/screens/Dashboard/ActionTab/index.tsx: -------------------------------------------------------------------------------- 1 | import ActionTab from "./ActionTab"; 2 | 3 | export default ActionTab; 4 | -------------------------------------------------------------------------------- /frontend/src/utils/sleep.ts: -------------------------------------------------------------------------------- 1 | export const sleep = (ms: number) => 2 | new Promise((resolve) => setTimeout(resolve, ms)); 3 | -------------------------------------------------------------------------------- /contracts/oracle/.docs/oracle_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/contracts/oracle/.docs/oracle_diagram.png -------------------------------------------------------------------------------- /frontend/src/assets/fonts/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/src/assets/fonts/Inter-Bold.ttf -------------------------------------------------------------------------------- /frontend/src/assets/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/src/assets/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /frontend/src/assets/fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/src/assets/fonts/Inter-Regular.ttf -------------------------------------------------------------------------------- /frontend/src/assets/fonts/Inter-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/frontend/src/assets/fonts/Inter-SemiBold.ttf -------------------------------------------------------------------------------- /services/liquidator/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod indexer_utils; 2 | pub mod market_utils; 3 | pub mod oracle_utils; 4 | pub mod print_swaygang_sign; 5 | -------------------------------------------------------------------------------- /contracts/oracle/.docs/oracle-logo-dark-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/contracts/oracle/.docs/oracle-logo-dark-theme.png -------------------------------------------------------------------------------- /libraries/i64/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alexey"] 3 | entry = "main.sw" 4 | license = "Apache-2.0" 5 | name = "i64" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /contracts/market/tests/artefacts/oracle/oracle.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/contracts/market/tests/artefacts/oracle/oracle.bin -------------------------------------------------------------------------------- /contracts/oracle/.docs/oracle-logo-light-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/contracts/oracle/.docs/oracle-logo-light-theme.png -------------------------------------------------------------------------------- /contracts/oracle/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alex Nagorny "] 3 | entry = "main.sw" 4 | license = "Apache-2.0" 5 | name = "oracle" 6 | -------------------------------------------------------------------------------- /frontend/src/utils/toUpperFirstLetter.ts: -------------------------------------------------------------------------------- 1 | export default function toUpperFirstLetter(str: string) { 2 | return str.charAt(0).toUpperCase() + str.slice(1); 3 | } 4 | -------------------------------------------------------------------------------- /contracts/market/tests/artefacts/factory/token-factory.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compolabs/sway-lend/HEAD/contracts/market/tests/artefacts/factory/token-factory.bin -------------------------------------------------------------------------------- /frontend/src/utils/isRoutesEquals.ts: -------------------------------------------------------------------------------- 1 | const isRoutesEquals = (a: string, b: string) => 2 | a.replaceAll("/", "") === b.replaceAll("/", ""); 3 | export default isRoutesEquals; 4 | -------------------------------------------------------------------------------- /abi/oracle_abi/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alex Nagorny "] 3 | entry = "main.sw" 4 | license = "Apache-2.0" 5 | name = "oracle_abi" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/minus-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/themes/darkTheme/index.ts: -------------------------------------------------------------------------------- 1 | import colors from "./colors"; 2 | import images from "./images"; 3 | // eslint-disable-next-line 4 | export default { 5 | colors, 6 | images, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/themes/lightTheme/index.ts: -------------------------------------------------------------------------------- 1 | import colors from "./colors"; 2 | import images from "./images"; 3 | // eslint-disable-next-line 4 | export default { 5 | colors, 6 | images, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/utils/getWordsFromValue.ts: -------------------------------------------------------------------------------- 1 | export function getWordsFromValue(value?: string | string[]) { 2 | if (!Array.isArray(value)) { 3 | return value?.split(" "); 4 | } 5 | return value; 6 | } 7 | -------------------------------------------------------------------------------- /contracts/market/tests/testnet_tests/mod.rs: -------------------------------------------------------------------------------- 1 | mod absorb_test; 2 | mod availtable_to_borrow_test; 3 | mod debug_state; 4 | mod deploy; 5 | mod get_user_supply_borrow; 6 | mod main_test; 7 | mod withdraw_collateral; 8 | -------------------------------------------------------------------------------- /scripts/get_account_state/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alexey"] 3 | entry = "main.sw" 4 | license = "Apache-2.0" 5 | name = "get_account_state" 6 | 7 | [dependencies] 8 | market_abi = { path = "../../abi/market_abi" } -------------------------------------------------------------------------------- /abi/market_abi/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alexey"] 3 | entry = "abi.sw" 4 | license = "Apache-2.0" 5 | name = "market_abi" 6 | 7 | [dependencies] 8 | i64 = { git = "https://github.com/compolabs/i64" } 9 | 10 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/themes/index.ts: -------------------------------------------------------------------------------- 1 | import darkThemeColors from "./darkTheme/colors"; 2 | import lightThemeColors from "./lightTheme/colors"; 3 | import { rem } from "./rem"; 4 | 5 | export { darkThemeColors, lightThemeColors, rem }; 6 | -------------------------------------------------------------------------------- /frontend/src/utils/centerEllipsis.ts: -------------------------------------------------------------------------------- 1 | export default function centerEllipsis(str: string, symbols = 10) { 2 | if (str.length <= symbols) return str; 3 | return `${str.slice(0, symbols / 2)}...${str.slice(-symbols / 2)}`; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/plus-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/components/Divider.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | const Divider = styled.div` 4 | width: 100%; 5 | height: 0.5px; 6 | background: ${({ theme }) => theme.colors.divider}; 7 | `; 8 | export default Divider; 9 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/arrowDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/hooks/useIsomorphicLayoutEffect.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useLayoutEffect } from "react"; 2 | 3 | const useIsomorphicLayoutEffect = 4 | typeof window !== "undefined" ? useLayoutEffect : useEffect; 5 | 6 | export default useIsomorphicLayoutEffect; 7 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/darkArrowDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/rightArrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/config/webpack/persistentCache/createEnvironmentHash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const { createHash } = require('crypto'); 3 | 4 | module.exports = env => { 5 | const hash = createHash('md5'); 6 | hash.update(JSON.stringify(env)); 7 | 8 | return hash.digest('hex'); 9 | }; 10 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/rightArrow-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /contracts/market/tests/utils/number_utils.rs: -------------------------------------------------------------------------------- 1 | // TODO: Add the ability to accept floats 2 | pub fn parse_units(num: u64, decimals: u64) -> u64 { 3 | num * 10u64.pow(decimals as u32) 4 | } 5 | 6 | pub fn format_units(num: u64, decimals: u64) -> f64 { 7 | num as f64 / 10u64.pow(decimals as u32) as f64 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/components/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import React, { AnchorHTMLAttributes } from "react"; 2 | 3 | export const Anchor: React.FC> = ({ 4 | children, 5 | ...rest 6 | }) => ( 7 | 8 | {children} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /frontend/src/components/Layout.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import { Column } from "@components/Flex"; 3 | 4 | const Layout = styled(Column)` 5 | width: 100%; 6 | max-width: 1300px; 7 | align-items: center; 8 | min-height: calc(100vh - 140px); 9 | `; 10 | 11 | export default Layout; 12 | -------------------------------------------------------------------------------- /frontend/src/utils/mnemonic.ts: -------------------------------------------------------------------------------- 1 | import { Mnemonic } from "@fuel-ts/mnemonic"; 2 | 3 | export function isValidMnemonic(phrase: string): boolean { 4 | const words = phrase.split(" "); 5 | const mnemonic = new Mnemonic(); 6 | return ( 7 | words.filter((w) => mnemonic.wordlist.includes(w)).length === Number(12) 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/themes/rem.ts: -------------------------------------------------------------------------------- 1 | import { rem as toRem } from "polished"; 2 | import { Undefinable } from "tsdef"; 3 | 4 | export const rem = (value?: string | number): Undefinable => { 5 | if (typeof value === "number") { 6 | return toRem(`${value}px`); 7 | } 8 | 9 | return value && value.endsWith("px") ? toRem(value) : value; 10 | }; 11 | -------------------------------------------------------------------------------- /contracts/market/src/events.sw: -------------------------------------------------------------------------------- 1 | library; 2 | 3 | use market_abi::{structs::*}; 4 | 5 | pub struct CollateralConfigurationEvent{configuration: CollateralConfiguration} 6 | 7 | pub struct UserBasicEvent{user_basic: UserBasic, address: Address} 8 | 9 | pub struct UserCollateralEvent{ 10 | address: Address, 11 | asset_id: b256, 12 | amount: u64, 13 | } -------------------------------------------------------------------------------- /libraries/i64/Forc.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "core" 3 | source = "path+from-root-AD80769CAE44474A" 4 | 5 | [[package]] 6 | name = "i64" 7 | source = "member" 8 | dependencies = ["std"] 9 | 10 | [[package]] 11 | name = "std" 12 | source = "git+https://github.com/fuellabs/sway?tag=v0.46.0#e75f14b03636bc96751a6760304a1a6d3eb5937d" 13 | dependencies = ["core"] 14 | -------------------------------------------------------------------------------- /contracts/oracle/Forc.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "core" 3 | source = "path+from-root-566CA1D5F8BEAFBF" 4 | 5 | [[package]] 6 | name = "oracle" 7 | source = "member" 8 | dependencies = ["std"] 9 | 10 | [[package]] 11 | name = "std" 12 | source = "git+https://github.com/fuellabs/sway?tag=v0.49.3#0dc6570377ee9c4a6359ade597fa27351e02a728" 13 | dependencies = ["core"] 14 | -------------------------------------------------------------------------------- /frontend/src/components/Img.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | const Root = styled.img<{ width?: string; height?: string; radius?: string }>` 4 | width: ${({ width }) => (width ? width : "24px")}; 5 | height: ${({ height }) => (height ? height : "24px")}; 6 | ${({ radius }) => radius && `border-radius:${radius}`}; 7 | `; 8 | 9 | export default Root; 10 | -------------------------------------------------------------------------------- /contracts/market/Forc.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | authors = ["Alex Nagorny "] 3 | entry = "main.sw" 4 | license = "Apache-2.0" 5 | name = "market" 6 | 7 | [dependencies] 8 | oracle_abi = { path = "../../abi/oracle_abi" } 9 | market_abi = { path = "../../abi/market_abi" } 10 | i64 = { git = "https://github.com/compolabs/i64" } 11 | # signed_integers = { git = "https://github.com/FuelLabs/sway-libs" } -------------------------------------------------------------------------------- /frontend/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/hooks/useVM.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export function useVM(storeContext: React.Context) { 4 | const store = React.useContext(storeContext); 5 | if (!store) { 6 | // this is especially useful in TypeScript so you don't need to be checking for null all the time 7 | throw new Error("useStore must be used within a StoreProvider."); 8 | } 9 | return store; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/stores/useStores.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import RootStore from "@stores/RootStore"; 3 | 4 | export const storesContext = React.createContext(null); 5 | 6 | export const useStores = () => { 7 | const rootStore = React.useContext(storesContext); 8 | if (rootStore == null) { 9 | throw new Error("No RootStore found i context"); 10 | } 11 | return rootStore; 12 | }; 13 | -------------------------------------------------------------------------------- /abi/oracle_abi/src/main.sw: -------------------------------------------------------------------------------- 1 | library ; 2 | 3 | abi Oracle { 4 | fn owner() -> Identity; 5 | #[storage(read, write)] 6 | fn set_price(asset_id: b256, price_value: u64); 7 | #[storage(read, write)] 8 | fn set_prices(prices: Vec<(b256, u64)>); 9 | #[storage(read)] 10 | fn get_price(asset_id: b256) -> Price; 11 | } 12 | struct Price { 13 | asset_id: b256, 14 | price: u64, 15 | last_update: u64, 16 | } -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # dependencies 3 | /node_modules 4 | /.pnp 5 | .pnp.js 6 | 7 | # testing 8 | /coverage 9 | 10 | # production 11 | /build 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | 24 | .idea 25 | .env 26 | -------------------------------------------------------------------------------- /frontend/src/components/HideElements.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | export const Mobile = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | width: 100%; 7 | @media (min-width: 880px) { 8 | display: none; 9 | } 10 | `; 11 | 12 | export const Desktop = styled.div` 13 | display: none; 14 | width: 100%; 15 | @media (min-width: 880px) { 16 | display: flex; 17 | flex-direction: column; 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /services/swaylend-indexer/swaylend_indexer.manifest.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | namespace: composabilitylabs 3 | identifier: swaylend_indexer 4 | abi: "./market-abi.json" 5 | fuel_client: ~ 6 | graphql_schema: schema/swaylend_indexer.schema.graphql 7 | module: 8 | wasm: target/wasm32-unknown-unknown/release/swaylend_indexer.wasm 9 | metrics: ~ 10 | contract_id: fuel18llu9z7mpfrqyclwm2d4d7w9z47gqjxztmg3dsayuh8w0zajfwus34ml3a 11 | start_block: 4593788 12 | end_block: ~ 13 | resumable: true 14 | -------------------------------------------------------------------------------- /services/swaylend-indexer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swaylend_indexer" 3 | version = "0.0.0" 4 | edition = "2021" 5 | publish = false 6 | rust-version = "1.73.0" 7 | 8 | [lib] 9 | crate-type = ['cdylib'] 10 | 11 | [dependencies] 12 | fuel-indexer-utils = { version = "0.23" } 13 | fuels = { version = "0.49", default-features = false } 14 | getrandom = { version = "0.2", features = ["js"] } 15 | serde = { version = "1.0", default-features = false, features = ["derive"] } 16 | -------------------------------------------------------------------------------- /frontend/src/components/SizedBox.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from "react"; 2 | interface IProps extends HTMLAttributes { 3 | width?: number; 4 | height?: number; 5 | } 6 | const SizedBox: React.FunctionComponent = ({ 7 | width, 8 | height, 9 | style, 10 | ...rest 11 | }) => ( 12 |
16 | ); 17 | 18 | export default SizedBox; 19 | -------------------------------------------------------------------------------- /frontend/src/stores/index.tsx: -------------------------------------------------------------------------------- 1 | import { storesContext, useStores } from "@stores/useStores"; 2 | 3 | import RootStore from "./RootStore"; 4 | import AccountStore from "./AccountStore"; 5 | import SettingsStore from "./SettingsStore"; 6 | import NotificationStore from "./NotificationStore"; 7 | import PricesStore from "./PricesStore"; 8 | 9 | export { 10 | RootStore, 11 | SettingsStore, 12 | AccountStore, 13 | NotificationStore, 14 | PricesStore, 15 | storesContext, 16 | useStores, 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/utils/localStorage.ts: -------------------------------------------------------------------------------- 1 | import { ISerializedRootStore } from "@stores/RootStore"; 2 | 3 | export const loadState = (): ISerializedRootStore | undefined => { 4 | try { 5 | const state = JSON.parse(localStorage.getItem("sway-lend-store") as string); 6 | return state || undefined; 7 | } catch (error) { 8 | console.dir(error); 9 | return undefined; 10 | } 11 | }; 12 | export const saveState = (state: ISerializedRootStore): void => { 13 | localStorage.setItem("sway-lend-store", JSON.stringify(state)); 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/moon-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/information.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /services/oracle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swaylend-oracle" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | dotenv = "0.15.0" 10 | fuels = { version = "0.48", features = ["fuel-core-lib"] } 11 | reqwest = "0.11.14" 12 | serde = "1.0.188" 13 | serde_json = "1.0.92" 14 | serenity = { default-features = false, features = ["client", "gateway", "model", "rustls_backend"], version = "0.11.5"} 15 | tokio = { version = "1.25.0", features = ["full"] } 16 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /frontend/src/hooks/useFuel.tsx: -------------------------------------------------------------------------------- 1 | import { Fuel } from "@fuel-wallet/sdk"; 2 | import { useState, useEffect } from "react"; 3 | 4 | export function useFuel() { 5 | const [error, setError] = useState(""); 6 | const [isLoading, setLoading] = useState(true); 7 | const [fuel] = useState(new Fuel({ name: "Fuel Wallet" })); 8 | 9 | useEffect(() => { 10 | fuel.hasWallet().then((hasWallet) => { 11 | setError(hasWallet ? "" : "fuel not detected on the window!"); 12 | setLoading(false); 13 | }); 14 | }, []); 15 | 16 | return [fuel as Fuel, error, isLoading] as const; 17 | } 18 | -------------------------------------------------------------------------------- /services/liquidator/src/utils/oracle_utils.rs: -------------------------------------------------------------------------------- 1 | use fuels::prelude::{abigen, WalletUnlocked}; 2 | 3 | abigen!(Contract( 4 | name = "OracleContract", 5 | abi = "src/artefacts/oracle-abi.json" 6 | )); 7 | 8 | pub mod oracle_abi_calls { 9 | 10 | use fuels::types::Bits256; 11 | 12 | use super::*; 13 | 14 | pub async fn get_price(contract: &OracleContract, asset_id: Bits256) -> Price { 15 | contract 16 | .methods() 17 | .get_price(asset_id) 18 | .simulate() 19 | .await 20 | .unwrap() 21 | .value 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/hooks/useHover.tsx: -------------------------------------------------------------------------------- 1 | import { RefObject, useState } from "react"; 2 | import useEventListener from "@src/hooks/useEventListener"; 3 | 4 | function useHover( 5 | elementRef: RefObject 6 | ): boolean { 7 | const [value, setValue] = useState(false); 8 | 9 | const handleMouseEnter = () => setValue(true); 10 | const handleMouseLeave = () => setValue(false); 11 | 12 | useEventListener("mouseenter", handleMouseEnter, elementRef); 13 | useEventListener("mouseleave", handleMouseLeave, elementRef); 14 | 15 | return value; 16 | } 17 | 18 | export default useHover; 19 | -------------------------------------------------------------------------------- /services/oracle/Dockerfile: -------------------------------------------------------------------------------- 1 | # Tells docker to use the latest Rust official image 2 | FROM rust:latest 3 | # Copy our current working directory into the container 4 | COPY ./ ./ 5 | # Create the release build 6 | RUN cargo build --release 7 | # Generate our self signed certs (change these parameters accordingly!) 8 | # RUN openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.rsa -out cert.pem \ 9 | # -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=example.com" 10 | # Expose the port our app is running on 11 | # EXPOSE 9231 12 | # Run the application! 13 | CMD ["./target/release/swaylend-oracle"] -------------------------------------------------------------------------------- /contracts/oracle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oracle" 3 | description = "A cargo-generate template for Rust + Sway integration testing." 4 | version = "0.1.0" 5 | edition = "2021" 6 | authors = ["alexey "] 7 | license = "Apache-2.0" 8 | 9 | [dev-dependencies] 10 | fuels = { version = "0.48", features = ["fuel-core-lib"] } 11 | tokio = { version = "1.12", features = ["rt", "macros"] } 12 | 13 | [[test]] 14 | harness = true 15 | name = "integration_tests" 16 | path = "tests/harness.rs" 17 | 18 | [dependencies] 19 | dotenv = "0.15.0" 20 | reqwest = "0.11.20" 21 | serde = "1.0.188" 22 | serde_json = "1.0.105" 23 | -------------------------------------------------------------------------------- /services/liquidator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Tells docker to use the latest Rust official image 2 | FROM rust:latest 3 | # Copy our current working directory into the container 4 | COPY ./ ./ 5 | # Create the release build 6 | RUN cargo build --release 7 | # Generate our self signed certs (change these parameters accordingly!) 8 | # RUN openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.rsa -out cert.pem \ 9 | # -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=example.com" 10 | # Expose the port our app is running on 11 | # EXPOSE 9231 12 | # Run the application! 13 | CMD ["./target/release/swaylend-liquidator"] -------------------------------------------------------------------------------- /frontend/src/contracts/index.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | 3 | /* tslint:disable */ 4 | /* eslint-disable */ 5 | 6 | /* 7 | Fuels version: 0.62.0 8 | Forc version: 0.44.0 9 | Fuel-Core version: 0.20.6 10 | */ 11 | 12 | export type { OracleAbi } from "./OracleAbi"; 13 | export type { MarketAbi } from "./MarketAbi"; 14 | export type { TokenFactoryAbi } from "./TokenFactoryAbi"; 15 | export { TokenFactoryAbi__factory } from "./factories/TokenFactoryAbi__factory"; 16 | 17 | export { OracleAbi__factory } from "./factories/OracleAbi__factory"; 18 | export { MarketAbi__factory } from "./factories/MarketAbi__factory"; 19 | -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Sway Lend", 3 | "name": "Sway Lend: Lending protocol built on Fuel Network", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/success.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/sun-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /docs/get-started-on-fuel/top-up-wallet.md: -------------------------------------------------------------------------------- 1 | # Top up wallet 2 | 3 | The next step is to acquire some funds in your wallet. To mint tokens on the Fuel network, you'll need to have some ETH in your wallet to pay transaction fees. There are two ways to obtain ETH: 4 | 5 | 1. The first is through the main [faucet link](https://faucet-beta-3.fuel.network). 6 | 2. The second is by visiting the [Faucet page](https://app.swaylend.com/#/faucet) on our app, which features a table with all tokens supported by our platform, including UNI, USDC, BTC, LINK, and Sway (the utility token for our application). Note that to mint any token other than ETH, you must have some ETH in your wallet first. 7 | -------------------------------------------------------------------------------- /services/liquidator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swaylend-liquidator" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | dotenv = "0.15.0" 10 | fuels = { version = "0.48", features = ["fuel-core-lib"] } 11 | reqwest = "0.11.20" 12 | serde = "1.0.188" 13 | serde_json = "1.0.107" 14 | serenity = { default-features = false, features = ["client", "gateway", "model", "rustls_backend"], version = "0.11.5"} 15 | tokio = { version = "1.25.0", features = ["full"] } 16 | src20_sdk = { git = "https://github.com/compolabs/src-20.git", branch = "token-factory"} 17 | -------------------------------------------------------------------------------- /contracts/market/tests/artefacts/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "kink": 800000000000000000, 3 | "supply_per_second_interest_rate_slope_low": 10000000000, 4 | "supply_per_second_interest_rate_slope_high": 100000000000, 5 | "borrow_per_second_interest_rate_slope_low": 25000000000, 6 | "borrow_per_second_interest_rate_slope_high": 187500000000, 7 | "borrow_per_second_interest_rate_base": 15854895992, 8 | "store_front_price_factor": 6000, 9 | "base_tracking_supply_speed": 1868287030000000, 10 | "base_tracking_borrow_speed": 3736574060000000, 11 | "base_min_for_rewards": 20000000, 12 | "base_borrow_min": 10000000, 13 | "target_reserves": 1000000000000 14 | } -------------------------------------------------------------------------------- /frontend/src/typings/emotion.d.ts: -------------------------------------------------------------------------------- 1 | import { themes } from "@src/themes/ThemeProvider"; 2 | 3 | import "@emotion/react"; 4 | 5 | export type TColorType = 6 | | typeof themes.darkTheme.colors 7 | | typeof themes.lightTheme.colors; 8 | export type TImagesType = 9 | | typeof themes.darkTheme.images 10 | | typeof themes.lightTheme.images; 11 | export type TSvgType = 12 | | typeof themes.darkTheme.svg 13 | | typeof themes.lightTheme.svg; 14 | 15 | declare module "@emotion/react" { 16 | // eslint-disable-next-line @typescript-eslint/naming-convention 17 | export interface Theme { 18 | colors: TColorType; 19 | images: TImagesType; 20 | svg: TSvgType; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frontend/config/jest/babelTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const babelJest = require('babel-jest').default; 4 | 5 | const hasJsxRuntime = (() => { 6 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { 7 | return false; 8 | } 9 | 10 | try { 11 | require.resolve('react/jsx-runtime'); 12 | return true; 13 | } catch (e) { 14 | return false; 15 | } 16 | })(); 17 | 18 | module.exports = babelJest.createTransformer({ 19 | presets: [ 20 | [ 21 | require.resolve('babel-preset-react-app'), 22 | { 23 | runtime: hasJsxRuntime ? 'automatic' : 'classic', 24 | }, 25 | ], 26 | ], 27 | babelrc: false, 28 | configFile: false, 29 | }); 30 | -------------------------------------------------------------------------------- /frontend/src/contracts/common.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | 3 | /* tslint:disable */ 4 | /* eslint-disable */ 5 | 6 | /* 7 | Fuels version: 0.62.0 8 | Forc version: 0.44.0 9 | Fuel-Core version: 0.20.6 10 | */ 11 | 12 | /* 13 | Mimics Sway Enum, requires at least one Key-Value but 14 | does not raise error on multiple pairs. 15 | This is done in the abi-coder 16 | */ 17 | export type Enum }> = Partial & 18 | U[keyof U]; 19 | 20 | /* 21 | Mimics Sway Option and Vectors. 22 | Vectors are treated like arrays in Typescript. 23 | */ 24 | export type Option = T | undefined; 25 | 26 | export type Vec = T[]; 27 | -------------------------------------------------------------------------------- /scripts/get_account_state/Forc.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "core" 3 | source = "path+from-root-AD80769CAE44474A" 4 | 5 | [[package]] 6 | name = "get_account_state" 7 | source = "member" 8 | dependencies = [ 9 | "market_abi", 10 | "std", 11 | ] 12 | 13 | [[package]] 14 | name = "i64" 15 | source = "path+from-root-E7D6EBB33B38526D" 16 | dependencies = ["std"] 17 | 18 | [[package]] 19 | name = "market_abi" 20 | source = "path+from-root-E7D6EBB33B38526D" 21 | dependencies = [ 22 | "i64", 23 | "std", 24 | ] 25 | 26 | [[package]] 27 | name = "std" 28 | source = "git+https://github.com/fuellabs/sway?tag=v0.46.0#e75f14b03636bc96751a6760304a1a6d3eb5937d" 29 | dependencies = ["core"] 30 | -------------------------------------------------------------------------------- /frontend/src/components/Dialog/Dialog.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import RcDialog from "rc-dialog"; 3 | import "rc-dialog/assets/index.css"; 4 | import "./styles.css"; 5 | import { IDialogPropTypes } from "rc-dialog/lib/IDialogPropTypes"; 6 | import { ReactComponent as CloseIcon } from "@src/assets/icons/close.svg"; 7 | 8 | interface IProps extends IDialogPropTypes {} 9 | 10 | const Dialog: React.FC = ({ children, ...rest }) => { 11 | return ( 12 | } 14 | animation="zoom" 15 | maskAnimation="fade" 16 | {...rest} 17 | > 18 | {children} 19 | 20 | ); 21 | }; 22 | export default Dialog; 23 | -------------------------------------------------------------------------------- /frontend/src/components/TokenIcon.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | type TokenIconSize = "default" | "small" | "tiny"; 4 | 5 | const TokenIcon = styled.img<{ size?: TokenIconSize }>` 6 | border: 1px solid rgba(0, 0, 0, 0.1); 7 | border-radius: 50%; 8 | box-sizing: border-box; 9 | box-shadow: none; 10 | color: transparent; 11 | object-fit: cover; 12 | ${({ size }) => 13 | (() => { 14 | switch (size) { 15 | case "tiny": 16 | return "width: 16px; height: 16px;"; 17 | case "small": 18 | return "width: 40px; height: 40px;"; 19 | default: 20 | return "width: 56px; height: 56px;"; 21 | } 22 | })()} 23 | `; 24 | 25 | export default TokenIcon; 26 | -------------------------------------------------------------------------------- /services/oracle/src/utils/oracle_abi_calls.rs: -------------------------------------------------------------------------------- 1 | pub mod oracle_abi_calls { 2 | 3 | use fuels::{ 4 | prelude::{TxParameters, WalletUnlocked}, 5 | programs::call_response::FuelCallResponse, 6 | types::Bits256, 7 | }; 8 | 9 | use crate::OracleContract; 10 | 11 | pub async fn set_prices( 12 | oracle: &OracleContract, 13 | prices: Vec<(Bits256, u64)>, 14 | ) -> Result, fuels::types::errors::Error> { 15 | let tx_params = TxParameters::default().with_gas_price(1); 16 | oracle 17 | .methods() 18 | .set_prices(prices) 19 | .tx_params(tx_params) 20 | .call() 21 | .await 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/components/Progressbar.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | 4 | interface IProps { 5 | percent: number; 6 | red?: boolean; 7 | } 8 | 9 | const Root = styled.div` 10 | width: 100%; 11 | height: 4px; 12 | background: ${({ theme }) => theme.colors.progressBar.secondary}; 13 | border-radius: 4px; 14 | 15 | .progress { 16 | border-radius: 4px; 17 | height: 4px; 18 | background: ${({ theme }) => theme.colors.progressBar.main}; 19 | } 20 | `; 21 | 22 | const Progressbar: React.FC = ({ percent }) => { 23 | return ( 24 | 25 |
26 | 27 | ); 28 | }; 29 | export default Progressbar; 30 | -------------------------------------------------------------------------------- /frontend/src/screens/Dashboard/SwitchActions.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import SwitchButtons from "@components/SwitchButtons"; 3 | import { useDashboardVM } from "@screens/Dashboard/DashboardVm"; 4 | import { observer } from "mobx-react-lite"; 5 | 6 | interface IProps {} 7 | 8 | const SwitchActions: React.FC = () => { 9 | const vm = useDashboardVM(); 10 | return ( 11 | { 15 | if (!vm.loading) { 16 | vm.setMode(v); 17 | vm.setAction(null); 18 | vm.setActionTokenAssetId(null); 19 | } 20 | }} 21 | /> 22 | ); 23 | }; 24 | export default observer(SwitchActions); 25 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/disconnect.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/attention.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/health-gradient.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/health-gradient-small.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /services/swaylend-indexer/schema/swaylend_indexer.schema.graphql: -------------------------------------------------------------------------------- 1 | type CollateralConfigurationEntity @entity { 2 | id: ID! 3 | asset_id: AssetId! 4 | price_feed: ContractId! 5 | decimals: U64! 6 | borrow_collateral_factor: U64! 7 | liquidate_collateral_factor: U64! 8 | liquidation_penalty: U64! 9 | supply_cap: U64! 10 | paused: Boolean! 11 | } 12 | 13 | type UserBasicEntity @entity { 14 | id: ID! 15 | address: Address! 16 | principal_absolute: U64! 17 | principal_negative: Boolean! 18 | base_tracking_index: U64! 19 | base_tracking_accrued: U64! 20 | reward_claimed: U64! 21 | } 22 | 23 | type UserCollateralEntity @entity { 24 | id: ID! 25 | address: Address! 26 | asset_id: AssetId! 27 | amount: U64! 28 | } -------------------------------------------------------------------------------- /contracts/market/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "market" 3 | description = "A cargo-generate template for Rust + Sway integration testing." 4 | version = "0.1.0" 5 | edition = "2021" 6 | authors = ["Alex Nagorny "] 7 | license = "Apache-2.0" 8 | 9 | [dev-dependencies] 10 | fuels = { version = "0.55", features = ["fuel-core-lib"] } 11 | tokio = { version = "1.12", features = ["rt", "macros"] } 12 | 13 | [[test]] 14 | harness = true 15 | name = "integration_tests" 16 | path = "tests/harness.rs" 17 | 18 | [dependencies] 19 | dotenv = "0.15.0" 20 | rand = "0.8.5" 21 | reqwest = "0.11.13" 22 | serde = "1.0.188" 23 | serde_json = "1.0.91" 24 | src20_sdk = { git = "https://github.com/compolabs/src-20.git", branch = "token-factory"} 25 | # src20_sdk = {path = "../../../src-20"} 26 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /docs/developers/contract-methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Description of all involved in protocol code 3 | --- 4 | 5 | # Contract overview 6 | 7 | The architecture of Sway Lend has been rewritten from the Ethereum lending protocol solution [Compound](https://compound.finance/) v3 to the Sway programming language. There are some differences in the number types due to Fuel's native asset system working on a 64-bit word size. 8 | 9 | This documentation will cover two topics related to the Sway Lend contracts: contract methods and storage entities. 10 | 11 | The contract methods section will discuss the functions available to interact with the contracts. 12 | 13 | In the storage entities section, we will explore the data stored by the contracts and the relationships between different storage values. 14 | -------------------------------------------------------------------------------- /contracts/market/Forc.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "core" 3 | source = "path+from-root-566CA1D5F8BEAFBF" 4 | 5 | [[package]] 6 | name = "i64" 7 | source = "path+from-root-9ED3421BB02FBE52" 8 | dependencies = ["std"] 9 | 10 | [[package]] 11 | name = "market" 12 | source = "member" 13 | dependencies = [ 14 | "i64", 15 | "market_abi", 16 | "oracle_abi", 17 | "std", 18 | ] 19 | 20 | [[package]] 21 | name = "market_abi" 22 | source = "path+from-root-9ED3421BB02FBE52" 23 | dependencies = [ 24 | "i64", 25 | "std", 26 | ] 27 | 28 | [[package]] 29 | name = "oracle_abi" 30 | source = "path+from-root-9ED3421BB02FBE52" 31 | dependencies = ["std"] 32 | 33 | [[package]] 34 | name = "std" 35 | source = "git+https://github.com/fuellabs/sway?tag=v0.49.3#0dc6570377ee9c4a6359ade597fa27351e02a728" 36 | dependencies = ["core"] 37 | -------------------------------------------------------------------------------- /frontend/src/components/Scrollbar/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | export const ScrollbarRoot = styled.span` 4 | .ps__rail-x, 5 | .ps__rail-y { 6 | z-index: 999; 7 | 8 | & > .ps__thumb-y { 9 | background-color: #f1f2fe; 10 | width: 6px !important; 11 | 12 | &:hover { 13 | background-color: #f1f2fe; 14 | } 15 | } 16 | 17 | & > .ps__thumb-x { 18 | background-color: #f1f2fe; 19 | height: 6px !important; 20 | 21 | &:hover { 22 | background-color: #f1f2fe; 23 | } 24 | } 25 | 26 | &:hover, 27 | &:focus, 28 | &.ps--clicking { 29 | background-color: transparent !important; 30 | 31 | & > .ps__thumb-y, 32 | & > .ps__thumb-x { 33 | background-color: #f1f2fe; 34 | } 35 | } 36 | } 37 | `; 38 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/whiteLink.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /frontend/src/assets/tokens/BUSD.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /frontend/src/themes/lightTheme/images.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line 2 | export default { 3 | icons: { 4 | logo: require("@src/assets/icons/logo.svg").default, 5 | arrowDown: require("@src/assets/icons/arrowDown.svg").default, 6 | dashboard: require("@src/assets/icons/dashboard.svg").default, 7 | analytics: require("@src/assets/icons/analytics.svg").default, 8 | wallet: require("@src/assets/icons/wallet.svg").default, 9 | sun: require("@src/assets/icons/sun.svg").default, 10 | moon: require("@src/assets/icons/moon.svg").default, 11 | coins: require("@src/assets/icons/coins.svg").default, 12 | plus: require("@src/assets/icons/plus.svg").default, 13 | minus: require("@src/assets/icons/minus.svg").default, 14 | rightArrow: require("@src/assets/icons/rightArrow.svg").default, 15 | key: require("@src/assets/icons/key-dark.svg").default, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /docs/welcome/faq/liquidations.md: -------------------------------------------------------------------------------- 1 | # Liquidations 2 | 3 | Liquidation is a safety mechanism that ensures that all new borrowing positions are protected. It's based on higher collateral factors than the ones used for borrowing. If a borrower's debt goes over the limits set by these collateral factors, their account becomes eligible for liquidation. 4 | 5 | A liquidator, which can be a bot, contract, or user, then takes over the borrower's collateral and returns its value, minus a penalty, to the borrower. This eliminates the borrower's debt and they typically receive a balance of the base asset as a result. The protocol pays for each liquidation using its reserves of the base asset and in return, it receives the collateral assets. If the reserves are lower than the target set by governance, liquidators can purchase the collateral at a discount using the base asset, which increases the protocol's base asset reserves. 6 | -------------------------------------------------------------------------------- /frontend/src/assets/tokens/BNB.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /frontend/src/hooks/useOnClickOutside.ts: -------------------------------------------------------------------------------- 1 | import { RefObject, useEffect } from "react"; 2 | 3 | type TAnyEvent = MouseEvent | TouchEvent; 4 | 5 | function useOnClickOutside( 6 | ref: RefObject, 7 | handler: (event: TAnyEvent) => void 8 | ): void { 9 | useEffect(() => { 10 | const listener = (event: TAnyEvent) => { 11 | const el = ref?.current; 12 | 13 | if (!el || el.contains(event.target as Node)) { 14 | return; 15 | } 16 | 17 | handler(event); 18 | }; 19 | 20 | document.addEventListener(`mousedown`, listener); 21 | document.addEventListener(`touchstart`, listener); 22 | 23 | return () => { 24 | document.removeEventListener(`mousedown`, listener); 25 | document.removeEventListener(`touchstart`, listener); 26 | }; 27 | }, [ref, handler]); 28 | } 29 | 30 | export default useOnClickOutside; 31 | -------------------------------------------------------------------------------- /frontend/src/constants/tokenLogos.ts: -------------------------------------------------------------------------------- 1 | import eth from "@src/assets/tokens/ethereum.svg"; 2 | import usdt from "@src/assets/tokens/usdt.svg"; 3 | import bnb from "@src/assets/tokens/BNB.svg"; 4 | import btc from "@src/assets/tokens/bitcoin.svg"; 5 | import busd from "@src/assets/tokens/BUSD.svg"; 6 | import usdc from "@src/assets/tokens/usdc.svg"; 7 | import uni from "@src/assets/tokens/uni.svg"; 8 | import chainlink from "@src/assets/tokens/chainlink.svg"; 9 | import sway from "@src/assets/tokens/sway.svg"; 10 | import compound from "@src/assets/tokens/compound.svg"; 11 | import unknown from "@src/assets/notFound.svg"; 12 | 13 | const tokenLogos: Record = { 14 | ETH: eth, 15 | USDT: usdt, 16 | BNB: bnb, 17 | BTC: btc, 18 | BUSD: busd, 19 | USDC: usdc, 20 | UNI: uni, 21 | LINK: chainlink, 22 | SWAY: sway, 23 | COMP: compound, 24 | UNKNOWN: unknown, 25 | }; 26 | 27 | export default tokenLogos; 28 | -------------------------------------------------------------------------------- /frontend/src/screens/TechnicalWork.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | import noPage from "@src/assets/404.svg"; 4 | import Text from "@components/Text"; 5 | 6 | interface IProps {} 7 | 8 | const Root = styled.div` 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | justify-content: center; 13 | height: calc(100vh - 140px); 14 | width: 100%; 15 | `; 16 | const Img = styled.img` 17 | max-width: 240px; 18 | height: auto; 19 | padding-bottom: 44px; 20 | `; 21 | const TechnicalWork: React.FC = () => { 22 | return ( 23 | 24 | noPage 25 | 26 | Please come later 27 | 28 | 29 | App is under construction 30 | 31 | 32 | ); 33 | }; 34 | export default TechnicalWork; 35 | -------------------------------------------------------------------------------- /frontend/src/components/Loading.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from "react"; 2 | import { useEffect, useState } from "react"; 3 | import { useTheme } from "@emotion/react"; 4 | 5 | interface IProps extends HTMLAttributes { 6 | big?: boolean; 7 | } 8 | 9 | const Loading: React.FC = ({ big, ...rest }) => { 10 | const [length, setLength] = useState(3); 11 | const theme = useTheme(); 12 | useEffect(() => { 13 | const interval = setInterval(() => { 14 | setLength(length === 3 ? 1 : length + 1); 15 | }, 200); 16 | return () => clearInterval(interval); 17 | }); 18 | return ( 19 | 23 | {big 24 | ? Array.from({ length }, () => "●").join("") 25 | : Array.from({ length }, () => ".").join("")} 26 | 27 | ); 28 | }; 29 | export default Loading; 30 | -------------------------------------------------------------------------------- /frontend/src/themes/darkTheme/images.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line 2 | export default { 3 | icons: { 4 | logo: require("@src/assets/icons/dark-logo.svg").default, 5 | arrowDown: require("@src/assets/icons/darkArrowDown.svg").default, 6 | dashboard: require("@src/assets/icons/dashboard-dark.svg").default, 7 | analytics: require("@src/assets/icons/analytics-dark.svg").default, 8 | wallet: require("@src/assets/icons/wallet-dark.svg").default, 9 | sun: require("@src/assets/icons/sun-dark.svg").default, 10 | moon: require("@src/assets/icons/moon-dark.svg").default, 11 | coins: require("@src/assets/icons/coins-dark.svg").default, 12 | plus: require("@src/assets/icons/plus-dark.svg").default, 13 | minus: require("@src/assets/icons/minus-dark.svg").default, 14 | rightArrow: require("@src/assets/icons/rightArrow-dark.svg").default, 15 | key: require("@src/assets/icons/key-dark.svg").default, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/utils/indexerUtils.ts: -------------------------------------------------------------------------------- 1 | import { INDEXER_URL } from "@src/constants"; 2 | import axios from "axios"; 3 | 4 | export type TCollateralConfiguration = { 5 | asset_id: string; 6 | borrow_collateral_factor: number; 7 | decimals: number; 8 | id: string; 9 | liquidate_collateral_factor: number; 10 | liquidation_penalty: number; 11 | paused: boolean; 12 | price_feed: string; 13 | supply_cap: number; 14 | }; 15 | export async function fetchCollateralConfigurations(): Promise< 16 | Array 17 | > { 18 | const query = 19 | "SELECT json_agg(t) FROM (SELECT * FROM composabilitylabs_swaylend_indexer.collateralconfigurationentity) t;"; 20 | const url = INDEXER_URL; 21 | const headers = { 22 | "Content-Type": "application/json", 23 | Accept: "application/json", 24 | }; 25 | return axios 26 | .request({ method: "POST", url, headers, data: { query } }) 27 | .then((v) => v.data.data[0]); 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/themes/ThemeProvider.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ThemeProvider } from "@emotion/react"; 3 | 4 | import darkTheme from "@src/themes/darkTheme"; 5 | import lightTheme from "@src/themes/lightTheme"; 6 | import { useStores } from "@stores"; 7 | import { Observer } from "mobx-react-lite"; 8 | 9 | export enum THEME_TYPE { 10 | LIGHT_THEME = "lightTheme", 11 | DARK_THEME = "darkTheme", 12 | } 13 | 14 | interface IProps { 15 | children: React.ReactNode; 16 | } 17 | 18 | export const themes = { 19 | darkTheme, 20 | lightTheme, 21 | }; 22 | //todo fix 23 | const ThemeWrapper: React.FC = ({ children }) => { 24 | const { settingsStore } = useStores(); 25 | return ( 26 | 27 | {() => ( 28 | 29 | {children} 30 | 31 | )} 32 | 33 | ); 34 | }; 35 | 36 | export default ThemeWrapper; 37 | -------------------------------------------------------------------------------- /Forc.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "core" 3 | source = "path+from-root-566CA1D5F8BEAFBF" 4 | 5 | [[package]] 6 | name = "i64" 7 | source = "git+https://github.com/compolabs/i64?default-branch#b983e37ec72b60a3544bde52babebec61b15c710" 8 | dependencies = ["std"] 9 | 10 | [[package]] 11 | name = "market" 12 | source = "member" 13 | dependencies = [ 14 | "i64", 15 | "market_abi", 16 | "oracle_abi", 17 | "std", 18 | ] 19 | 20 | [[package]] 21 | name = "market_abi" 22 | source = "path+from-root-9ED3421BB02FBE52" 23 | dependencies = [ 24 | "i64", 25 | "std", 26 | ] 27 | 28 | [[package]] 29 | name = "oracle" 30 | source = "member" 31 | dependencies = ["std"] 32 | 33 | [[package]] 34 | name = "oracle_abi" 35 | source = "path+from-root-9ED3421BB02FBE52" 36 | dependencies = ["std"] 37 | 38 | [[package]] 39 | name = "std" 40 | source = "git+https://github.com/fuellabs/sway?tag=v0.49.3#0dc6570377ee9c4a6359ade597fa27351e02a728" 41 | dependencies = ["core"] 42 | -------------------------------------------------------------------------------- /frontend/src/components/Dialog/styles.css: -------------------------------------------------------------------------------- 1 | .rc-dialog-mask { 2 | background: rgba(0, 0, 0, 0.4); 3 | } 4 | 5 | .rc-dialog-wrap { 6 | flex-direction: column; 7 | align-items: center; 8 | justify-content: center; 9 | display: flex; 10 | } 11 | 12 | .rc-dialog { 13 | width: calc(100% - 32px); 14 | } 15 | 16 | .rc-dialog-content { 17 | background: #ffffff; 18 | box-shadow: 0px 8px 56px rgba(54, 56, 112, 0.16); 19 | border-radius: 4px; 20 | overflow: hidden; 21 | min-height: 286px; 22 | padding: 0; 23 | } 24 | 25 | .rc-dialog-header { 26 | border-bottom: 1px solid #f1f2fe; 27 | padding: 16px; 28 | max-height: 56px; 29 | } 30 | 31 | .rc-dialog-body { 32 | padding: 16px 16px 0 16px; 33 | } 34 | 35 | .rc-dialog-title { 36 | font-family: Roboto, sans-serif; 37 | font-style: normal; 38 | font-weight: 500; 39 | font-size: 16px; 40 | line-height: 24px; 41 | color: #363870; 42 | } 43 | 44 | .rc-dialog-close { 45 | opacity: 1; 46 | } 47 | -------------------------------------------------------------------------------- /frontend/src/screens/Tutorial/Tutorial.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "@components/Layout"; 3 | import SizedBox from "@components/SizedBox"; 4 | import { useNavigate, useParams } from "react-router-dom"; 5 | import tutorials from "@src/constants/tutorials"; 6 | 7 | const Tutorial: React.FC = () => { 8 | const { tutorialId } = useParams<{ tutorialId: string }>(); 9 | const tutorial = tutorials.find(({ id }) => id === tutorialId); 10 | const navigate = useNavigate(); 11 | if (tutorial == null) navigate({ pathname: "/" }); 12 | return ( 13 | 14 | 15 | 26 | 27 | ); 28 | }; 29 | 30 | export default Tutorial; 31 | -------------------------------------------------------------------------------- /frontend/src/assets/tokens/usdt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /services/swaylend-indexer/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | postgres: 4 | image: postgres:latest 5 | ports: 6 | - "5432:5432" 7 | volumes: 8 | - .:/usr/local/postgres 9 | environment: 10 | - POSTGRES_PASSWORD=postgres 11 | - PGUSER=postgres 12 | healthcheck: 13 | test: ["CMD-SHELL", "pg_isready", "-U", "postgres", "-d", "postgres"] 14 | interval: 30s 15 | timeout: 60s 16 | retries: 5 17 | start_period: 80s 18 | fuel-indexer: 19 | image: ghcr.io/fuellabs/fuel-indexer:latest 20 | # image: ghcr.io/fuellabs/fuel-indexer:sha-94ee6d6 21 | command: bash -c "sleep 5 && ./fuel-indexer run --fuel-node-host beta-4.fuel.network --fuel-node-port 80 --postgres-host postgres --postgres-password postgres --web-api-host 0.0.0.0 --run-migrations --accept-sql-queries" 22 | ports: 23 | - "80:29987" 24 | volumes: 25 | - .:/usr/local/fuel-indexer 26 | depends_on: 27 | - postgres -------------------------------------------------------------------------------- /frontend/src/hooks/useIsConnected.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { useFuel } from "./useFuel"; // Импортируем useFuel 3 | 4 | export function useIsConnected() { 5 | const [fuel] = useFuel(); // Используем хук useFuel для получения fuel 6 | 7 | const [isConnected, setIsConnected] = useState(false); 8 | 9 | useEffect(() => { 10 | async function handleConnection() { 11 | if (fuel) { 12 | // Используем fuel из хука useFuel 13 | const isConnected = await fuel.isConnected(); 14 | setIsConnected(isConnected); 15 | } 16 | } 17 | 18 | if (fuel) { 19 | // Используем fuel из хука useFuel 20 | handleConnection(); 21 | } 22 | 23 | fuel?.on(fuel.events.connection, handleConnection); // Используем fuel из хука useFuel 24 | return () => { 25 | fuel?.off(fuel.events.connection, handleConnection); // Используем fuel из хука useFuel 26 | }; 27 | }, [fuel]); 28 | 29 | return [isConnected]; 30 | } 31 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body.noscroll { 2 | overflow-y: hidden; 3 | } 4 | 5 | a { 6 | text-decoration: none; 7 | } 8 | 9 | #root { 10 | display: flex; 11 | flex-direction: column; 12 | width: 100%; 13 | align-items: center; 14 | flex: 1 1 auto; 15 | } 16 | 17 | @font-face { 18 | font-family: "Inter"; 19 | font-weight: normal; 20 | src: local("Roboto"), url(assets/fonts/Inter-Regular.ttf) format("truetype"); 21 | } 22 | 23 | @font-face { 24 | font-family: "Inter"; 25 | src: local("Roboto"), url(assets/fonts/Inter-Medium.ttf) format("truetype"); 26 | font-weight: 500; 27 | } 28 | 29 | @font-face { 30 | font-family: "Inter"; 31 | src: local("Roboto"), url(assets/fonts/Inter-SemiBold.ttf) format("truetype"); 32 | font-weight: 600; 33 | } 34 | 35 | @font-face { 36 | font-family: "Inter"; 37 | src: local("Roboto"), url(assets/fonts/Inter-Bold.ttf) format("truetype"); 38 | font-weight: 700; 39 | } 40 | 41 | .Toastify__toast-icon { 42 | display: none !important; 43 | } 44 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx", 22 | "baseUrl": ".", 23 | "paths": { 24 | "@src": ["src"], 25 | "@src/*": ["src/*"], 26 | "@components": ["src/components"], 27 | "@components/*": ["src/components/*"], 28 | "@stores": ["src/stores"], 29 | "@stores/*": ["src/stores/*"], 30 | "@screens": ["src/screens"], 31 | "@screens/*": ["src/screens/*"] 32 | } 33 | }, 34 | "include": [ 35 | "src" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /frontend/src/components/Scrollbar/Scrollbar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PerfectScrollbar, { ScrollBarProps } from "react-perfect-scrollbar"; 3 | 4 | import { ScrollbarRoot } from "./styles"; 5 | 6 | interface IScrollbarProps extends ScrollBarProps { 7 | onScrollX?: (ref: any) => void; 8 | suppressScrollX?: boolean; 9 | suppressScrollY?: boolean; 10 | containerRef?: (ref: HTMLElement) => void; 11 | } 12 | 13 | const Scrollbar: React.FC = ({ 14 | children, 15 | suppressScrollX, 16 | suppressScrollY, 17 | containerRef, 18 | onScrollX, 19 | className, 20 | ...rest 21 | }) => ( 22 | 23 | 33 | {children} 34 | 35 | 36 | ); 37 | export default Scrollbar; 38 | -------------------------------------------------------------------------------- /frontend/src/components/Header/DarkMode.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React, { HTMLAttributes } from "react"; 3 | import Text from "@components/Text"; 4 | import Switch from "@components/Switch"; 5 | import { observer } from "mobx-react-lite"; 6 | import { useStores } from "@stores"; 7 | import { THEME_TYPE } from "@src/themes/ThemeProvider"; 8 | 9 | interface IProps extends HTMLAttributes { 10 | text?: boolean; 11 | } 12 | 13 | const Root = styled.div` 14 | display: flex; 15 | border-radius: 12px; 16 | gap: 11px; 17 | align-items: center; 18 | `; 19 | 20 | const DarkMode: React.FC = ({ text, ...rest }) => { 21 | const { settingsStore } = useStores(); 22 | return ( 23 | 24 | {text && Dark mode} 25 | settingsStore.toggleTheme()} 27 | value={settingsStore.selectedTheme === THEME_TYPE.DARK_THEME} 28 | /> 29 | 30 | ); 31 | }; 32 | export default observer(DarkMode); 33 | -------------------------------------------------------------------------------- /frontend/src/assets/tokens/chainlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /frontend/src/screens/Dashboard/AvailableToBorrow.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useStores } from "@stores"; 3 | import { Column, Row } from "@components/Flex"; 4 | import Text from "@components/Text"; 5 | import SizedBox from "@components/SizedBox"; 6 | import Progressbar from "@components/Progressbar"; 7 | import { observer } from "mobx-react-lite"; 8 | 9 | interface IProps {} 10 | 11 | const AvailableToBorrow: React.FC = observer(() => { 12 | const { accountStore } = useStores(); 13 | if (!accountStore.isLoggedIn) return null; 14 | return ( 15 | 16 | 17 | 18 | Available to Borrow 19 | 20 | 21 | 60% 22 | 23 | 24 | 25 | 26 | 27 | ); 28 | }); 29 | export default AvailableToBorrow; 30 | -------------------------------------------------------------------------------- /scripts/get_account_state/src/main.sw: -------------------------------------------------------------------------------- 1 | script; 2 | 3 | use std::constants::ZERO_B256; 4 | use market_abi::{Market, structs::*}; 5 | 6 | fn main() -> ( 7 | Vec, 8 | Vec<(b256, u64)> 9 | ) { 10 | let contract_address = 0x3fffc28bdb0a460263eeda9b56f9c5157c8048c25ed116c3a4e5cee78bb24bb9; 11 | let market = abi(Market, contract_address); 12 | let collateral_configurations = market.get_collateral_configurations(); 13 | 14 | let mut totals_collateral: Vec<(b256, u64)> = Vec::new(); 15 | let mut index = 0; 16 | while index < collateral_configurations.len() { 17 | let config = collateral_configurations.get(index); 18 | if config.is_some(){ 19 | let config = config.unwrap(); 20 | let collateral_configuration = market.totals_collateral(config.asset_id); 21 | totals_collateral.push((config.asset_id, collateral_configuration)); 22 | } 23 | index += 1; 24 | } 25 | 26 | ( 27 | collateral_configurations, 28 | totals_collateral 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/coins.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/coins-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/key-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | ## ⚡ WELCOME 4 | 5 | * [Introduction](README.md) 6 | * [Team](welcome/team.md) 7 | * [FAQ](welcome/faq/README.md) 8 | * [Supplying & Earning](welcome/faq/supplying-and-earning.md) 9 | * [Borrowing](welcome/faq/borrowing.md) 10 | * [Liquidations](welcome/faq/liquidations.md) 11 | 12 | ## 🎯 Get started 13 | 14 | * [Create wallet](get-started-on-fuel/create-wallet.md) 15 | * [Top up wallet](get-started-on-fuel/top-up-wallet.md) 16 | 17 | *** 18 | 19 | * [Interest Rates](interest-rates.md) 20 | * [Collateral & Borrowing](collateral-and-borrowing.md) 21 | 22 | ## 🌴 Developers 23 | 24 | * [Contract overview](developers/contract-methods.md) 25 | * [Contract methods](developers/contract-overview/contract-methods.md) 26 | * [Contract storage](developers/contract-overview/contract-storage.md) 27 | 28 | *** 29 | 30 | * [Risks](risks.md) 31 | 32 | ## 🔗 Links 33 | 34 | * [Web App](https://app.swaylend.com/) 35 | * [Github Repo](https://github.com/sway-gang/sway-lend) 36 | * [Discord](https://discord.gg/Fwpqpk6vDB) 37 | * [Twitter](https://twitter.com/swaylend) 38 | -------------------------------------------------------------------------------- /frontend/src/constants/tutorials.ts: -------------------------------------------------------------------------------- 1 | import walletConnect from "@src/assets/tutorials/connect.svg"; 2 | import mintETH from "@src/assets/tutorials/mint.svg"; 3 | import supplyCollateral from "@src/assets/tutorials/supply.svg"; 4 | import borrow from "@src/assets/tutorials/borrowUSDC.svg"; 5 | 6 | const tutorials = [ 7 | { 8 | id: "connect", 9 | title: "#0: Wallet connection", 10 | complexity: "Low", 11 | time: "10 min", 12 | pic: walletConnect, 13 | link: "https://docs.google.com/forms/d/e/1FAIpQLScqNaQ-oH-gfSabxW7k5qfMLNttSwNucOdKRVJemL1bvy0Guw/viewform?embedded=true", 14 | }, 15 | { 16 | id: "mint", 17 | title: "#1: Mint of ETH and collateral", 18 | complexity: "Medium", 19 | time: "15 min", 20 | pic: mintETH, 21 | }, 22 | { 23 | id: "supply", 24 | title: "#2: Supply of the collateral", 25 | complexity: "Low", 26 | time: "10 min", 27 | pic: supplyCollateral, 28 | }, 29 | { 30 | id: "borrow", 31 | title: "#3: Borrow", 32 | complexity: "Low", 33 | time: "10 min", 34 | pic: borrow, 35 | }, 36 | ]; 37 | export default tutorials; 38 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/analytics.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/components/Wallet/Wallet.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | import { useStores } from "@stores"; 4 | import { observer } from "mobx-react-lite"; 5 | import Button from "@components/Button"; 6 | import LoggedInAccountInfo from "@components/Wallet/LoggedInAccountInfo"; 7 | import LoginModal from "./LoginModal"; 8 | 9 | interface IProps {} 10 | 11 | const Root = styled.div` 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | width: 100%; 16 | `; 17 | 18 | const Wallet: React.FC = () => { 19 | const { accountStore, settingsStore } = useStores(); 20 | return ( 21 | 22 | {accountStore.address == null ? ( 23 | 26 | ) : ( 27 | 28 | )} 29 | settingsStore.setLoginModalOpened(false)} 32 | /> 33 | 34 | ); 35 | }; 36 | export default observer(Wallet); 37 | -------------------------------------------------------------------------------- /frontend/src/assets/icons/analytics-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/components/Wallet/LoginType.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React, { HTMLAttributes } from "react"; 3 | import Text from "@components/Text"; 4 | // import SizedBox from "@components/SizedBox"; 5 | import { useTheme } from "@emotion/react"; 6 | import Img from "@components/Img"; 7 | 8 | interface IProps extends HTMLAttributes { 9 | title: string; 10 | active: boolean; 11 | } 12 | 13 | const Root = styled.div<{ disable?: boolean }>` 14 | display: flex; 15 | flex-direction: row; 16 | width: 100%; 17 | justify-content: space-between; 18 | padding: 10px 0; 19 | border-bottom: 1px solid ${({ theme }) => theme.colors.divider}; 20 | box-sizing: border-box; 21 | cursor: ${({ disable }) => (disable ? "not-allowed" : "pointer")}; 22 | `; 23 | 24 | const LoginType: React.FC = ({ title, onClick, active, ...rest }) => { 25 | const theme = useTheme(); 26 | return ( 27 | 28 | {title} 29 | rightArrow 30 | 31 | ); 32 | }; 33 | export default LoginType; 34 | -------------------------------------------------------------------------------- /docs/risks.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Risks associated with supplying and borrowing 3 | --- 4 | 5 | # Risks 6 | 7 | ### **Asset Risk** 8 | 9 | Crypto assets are volatile and are subject to many risks, including but not limited to adoption, speculation, regulatory change, technology, and security risks. Any asset may be subject to large swings in value and may even become worthless, but Compound V3 architecture makes risk limited. 10 | 11 | ### **Smart Contract Risk** 12 | 13 | We do our best to prevent all possible attacks. However, the risk of exploitation can never be fully eliminated. 14 | 15 | {% hint style="info" %} 16 | Note as the protocol is currently in the alpha testing phase, updates to the contracts may result in the loss of funds. 17 | {% endhint %} 18 | 19 | ### **Liquidation** 20 | 21 | If the value of Supplier collateral dips below the threshold determined by asset LTV (loan-to-value ratios), a portion of the debt will be liquidated with a liquidation penalty deducted from the deposited collateral. 22 | 23 | Crypto assets are highly volatile. Due to sharp price fluctuations, liquidation may occur suddenly. There is a possibility that supplied collateral will not cover a debt position. 24 | -------------------------------------------------------------------------------- /frontend/src/hooks/useWindowSize.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | interface Size { 4 | width: number | undefined; 5 | height: number | undefined; 6 | } 7 | 8 | function useWindowSize(): Size { 9 | // Initialize state with undefined width/height so server and client renders match 10 | // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/ 11 | const [windowSize, setWindowSize] = useState({ 12 | width: undefined, 13 | height: undefined, 14 | }); 15 | useEffect(() => { 16 | // Handler to call on window resize 17 | function handleResize() { 18 | // Set window width/height to state 19 | setWindowSize({ 20 | width: window.innerWidth, 21 | height: window.innerHeight, 22 | }); 23 | } 24 | // Add event listener 25 | window.addEventListener("resize", handleResize); 26 | // Call handler right away so state gets updated with initial window size 27 | handleResize(); 28 | // Remove event listener on cleanup 29 | return () => window.removeEventListener("resize", handleResize); 30 | }, []); // Empty array ensures that effect is only run on mount 31 | return windowSize; 32 | } 33 | export default useWindowSize; 34 | -------------------------------------------------------------------------------- /frontend/src/components/TextArea.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | import React from "react"; 3 | 4 | interface IProps 5 | extends Omit< 6 | React.DetailedHTMLProps< 7 | React.InputHTMLAttributes, 8 | HTMLInputElement 9 | >, 10 | "onChange" | "prefix" 11 | > { 12 | value: string; 13 | onChange: (e: string) => void; 14 | error?: boolean; 15 | } 16 | 17 | const Root = styled.textarea<{ error?: boolean }>` 18 | background: transparent; 19 | resize: none; 20 | font-weight: 600; 21 | font-size: 20px; 22 | line-height: 32px; 23 | 24 | letter-spacing: -0.02em; 25 | border-radius: 4px; 26 | outline: none; 27 | color: ${({ theme }) => theme.colors.text}; 28 | border: 1px solid 29 | ${({ theme, error }) => 30 | error ? theme.colors.secondary1 : theme.colors.textArea.borderColor}; 31 | width: calc(100% - 6px); 32 | min-height: 160px; 33 | 34 | .scroll::-webkit-scrollbar { 35 | display: none; 36 | } 37 | `; 38 | 39 | const TextArea: React.FC = ({ onChange, value, error }) => { 40 | return ( 41 | onChange(e.target.value)} 44 | value={value} 45 | /> 46 | ); 47 | }; 48 | export default TextArea; 49 | -------------------------------------------------------------------------------- /frontend/src/stores/RootStore.ts: -------------------------------------------------------------------------------- 1 | import { makeAutoObservable } from "mobx"; 2 | import AccountStore, { ISerializedAccountStore } from "@stores/AccountStore"; 3 | import SettingsStore, { ISerializedSettingsStore } from "@stores/SettingsStore"; 4 | import NotificationStore from "@stores/NotificationStore"; 5 | import PricesStore from "@stores/PricesStore"; 6 | 7 | export interface ISerializedRootStore { 8 | accountStore?: ISerializedAccountStore; 9 | settingsStore?: ISerializedSettingsStore; 10 | } 11 | 12 | export default class RootStore { 13 | public accountStore: AccountStore; 14 | public settingsStore: SettingsStore; 15 | public notificationStore: NotificationStore; 16 | public pricesStore: PricesStore; 17 | 18 | constructor(initState?: ISerializedRootStore) { 19 | this.accountStore = new AccountStore(this, initState?.accountStore); 20 | this.settingsStore = new SettingsStore(this, initState?.settingsStore); 21 | this.notificationStore = new NotificationStore(this); 22 | this.pricesStore = new PricesStore(this); 23 | makeAutoObservable(this); 24 | } 25 | 26 | serialize = (): ISerializedRootStore => ({ 27 | accountStore: this.accountStore.serialize(), 28 | settingsStore: this.settingsStore.serialize(), 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /frontend/src/components/Card.tsx: -------------------------------------------------------------------------------- 1 | import styled from "@emotion/styled"; 2 | 3 | const Card = styled.div<{ 4 | maxWidth?: number; 5 | paddingDesktop?: string; 6 | paddingMobile?: string; 7 | justifyContent?: 8 | | "start" 9 | | "flex-end" 10 | | "space-around" 11 | | "space-between" 12 | | "center"; 13 | alignItems?: 14 | | "start" 15 | | "end" 16 | | "center" 17 | | "inherit" 18 | | "unset" 19 | | "flex-end" 20 | | "flex-start" 21 | | "baseline"; 22 | flexDirection?: "column" | "row"; 23 | type?: "white" | "dark"; 24 | bordered?: boolean; 25 | }>` 26 | display: flex; 27 | flex-direction: ${({ flexDirection }) => flexDirection ?? "column"}; 28 | justify-content: ${({ justifyContent }) => justifyContent ?? "default"}; 29 | align-items: ${({ alignItems }) => alignItems ?? "default"}; 30 | max-width: ${({ maxWidth }) => `${maxWidth}px` ?? "100%"}; 31 | border: none; 32 | width: 100%; 33 | border-radius: 4px; 34 | box-sizing: border-box; 35 | padding: ${({ paddingMobile }) => paddingMobile ?? "20px"}; 36 | background: ${({ theme }) => theme.colors.card.background}; 37 | @media (min-width: 560px) { 38 | padding: ${({ paddingDesktop }) => paddingDesktop ?? "16px 24px"}; 39 | } 40 | `; 41 | export default Card; 42 | -------------------------------------------------------------------------------- /frontend/src/constants/tokens.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Ethereum", 4 | "symbol": "ETH", 5 | "decimals": 9, 6 | "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000" 7 | }, 8 | { 9 | "name": "Bitcoin", 10 | "symbol": "BTC", 11 | "decimals": 8, 12 | "assetId": "0x49fab925448594b61c280b5c580b2a63a6f6a8aaa3c199a06798b1c568808158" 13 | }, 14 | { 15 | "name": "USDC", 16 | "symbol": "USDC", 17 | "decimals": 6, 18 | "assetId": "0x8bf7951ea3222fe0bae9b811c2b142a1ff417361dcf7457855ed477d2d9a8550" 19 | }, 20 | { 21 | "name": "Uniswap", 22 | "symbol": "UNI", 23 | "decimals": 9, 24 | "assetId": "0xae37bc0feb66e60a89e301d450bb4640aa9bd7cedd856e253e23989eae536e92" 25 | }, 26 | { 27 | "name": "Chainlink", 28 | "symbol": "LINK", 29 | "decimals": 9, 30 | "assetId": "0xfa36ce38f74ee0bcd12c11ec367ca237cee3e6b7a937761f4f762bbc11d2da21" 31 | }, 32 | { 33 | "name": "Sway", 34 | "symbol": "SWAY", 35 | "decimals": 9, 36 | "assetId": "0xcb3bc832cf32125ce4bd559022aa1b50ff2ac64c578c6343808457a78c1c799a" 37 | }, 38 | { 39 | "name": "Compound", 40 | "symbol": "COMP", 41 | "decimals": 9, 42 | "assetId": "0xc23da8f4073523e84e4fdd2b6a28f3273af2b70361345a63307313f0f489c48b" 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /docs/welcome/faq/supplying-and-earning.md: -------------------------------------------------------------------------------- 1 | # Supplying & Earning 2 | 3 | ### How to supply? 4 | 5 | 1. Go to the [Dashboard](https://app.swaylend.com/#/dashboard) page. 6 | 2. If you want to supply a base token such as USDC, click on the "Supply USDC" button (if available with a positive USDC balance in your account). 7 | 3. Enter the amount you want to supply. The same process applies to collateral tokens, but the action button can be found with the plus symbol in the assets table. 8 | 4. Submit the transaction and wait for it to be confirmed. Once confirmed, your supply is registered and you start earning interest. 9 | 10 | {% hint style="info" %} 11 | There is no minimum or maximum limit for supplying assets, but it's recommended to consider the transaction cost for low amounts, as it may be higher than the expected earnings. 12 | {% endhint %} 13 | 14 | ### How to withdraw? 15 | 16 | 1. Go to the [Dashboard](https://app.swaylend.com/#/dashboard) page. 17 | 2. Click on "Withdraw USDC" or the minus symbol in the token table. 18 | 3. Enter the amount you want to withdraw. 19 | 4. Submit the transaction. 20 | 21 | {% hint style="info" %} 22 | Make sure there is enough liquidity in your account before withdrawing, otherwise you will need to wait for more liquidity from suppliers or borrowers repaying. 23 | {% endhint %} 24 | -------------------------------------------------------------------------------- /frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | import { observer } from "mobx-react-lite"; 4 | import { Column } from "@components/Flex"; 5 | import Header from "@components/Header/Header"; 6 | import { Navigate, Route, Routes } from "react-router-dom"; 7 | import { ROUTES } from "@src/constants"; 8 | import Faucet from "@screens/Faucet"; 9 | import Dashboard from "@screens/Dashboard"; 10 | import Footer from "@components/Footer"; 11 | import Tutorials from "@screens/Tutorials"; 12 | import Tutorial from "@screens/Tutorial"; 13 | 14 | const Root = styled(Column)` 15 | width: 100%; 16 | align-items: center; 17 | background: ${({ theme }) => theme.colors.mainBackground}; 18 | min-height: 100vh; 19 | `; 20 | const App: React.FC = () => { 21 | return ( 22 | 23 |
24 | 25 | } /> 26 | } /> 27 | } /> 28 | } /> 29 | } /> 30 | 31 |