diff --git a/.env b/.env index 4b02b90e..f0e215e2 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ SASS_PATH=node_modules:src/styles REACT_APP_MAINNET_SERVICE_URL=https://api.terraswap.io -REACT_APP_TESTNET_SERVICE_URL=https://api-bombay.terraswap.io +REACT_APP_TESTNET_SERVICE_URL=https://api-pisco.terraswap.io REACT_APP_MAINNET_DASHBOARD_URL=https://api.terraswap.io/dashboard -REACT_APP_TESTNET_DASHBOARD_URL=https://api-bombay.terraswap.io/dashboard +REACT_APP_TESTNET_DASHBOARD_URL=https://api-pisco.terraswap.io/dashboard diff --git a/.env.development b/.env.development index 0f2d196a..ca8c6d92 100644 --- a/.env.development +++ b/.env.development @@ -4,6 +4,6 @@ REACT_APP_MAINNET_SERVICE_PROXY_URL=https://api.terraswap.io REACT_APP_MAINNET_DASHBOARD_URL=/api/mainnet/dashboard REACT_APP_MAINNET_DASHBOARD_PROXY_URL=https://api.terraswap.io/dashboard REACT_APP_TESTNET_SERVICE_URL=/api/testnet -REACT_APP_TESTNET_SERVICE_PROXY_URL=https://api-bombay.terraswap.io +REACT_APP_TESTNET_SERVICE_PROXY_URL=https://api-pisco.terraswap.io REACT_APP_TESTNET_DASHBOARD_URL=/api/testnet/dashboard -REACT_APP_TESTNET_DASHBOARD_PROXY_URL=https://api-bombay.terraswap.io/dashboard \ No newline at end of file +REACT_APP_TESTNET_DASHBOARD_PROXY_URL=https://api-pisco.terraswap.io/dashboard \ No newline at end of file diff --git a/.github/workflows/classic.yml b/.github/workflows/classic.yml new file mode 100644 index 00000000..86b22e54 --- /dev/null +++ b/.github/workflows/classic.yml @@ -0,0 +1,57 @@ +# This is a basic workflow to help you get started with Actions + +name: app-classic + +# Controls when the workflow will run +on: + push: + branches: [ "classic" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + deploy: + name: Build, Deploy to S3 bucket + runs-on: [ubuntu-latest] + + strategy: + matrix: + node-version: [17.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install yarn + run: npm install --location=global yarn + + - name: Package install + run: yarn + + - name: Build + run: CI=false yarn build + + - name: Transfer to S3 for serving static + uses: jakejarvis/s3-sync-action@master + with: + args: --acl public-read --follow-symlinks --delete + env: + AWS_S3_BUCKET: app-classic.terraswap.io + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + AWS_REGION: ap-northeast-2 + SOURCE_DIR: 'build' + + - name: Invalidate Cloudfront Distribution + uses: awact/cloudfront-action@master + env: + SOURCE_PATH: '/*' + AWS_REGION: ap-northeast-2 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + DISTRIBUTION_ID: ${{ secrets.DISTRIBUTION_ID_APP_CLASSIC }} \ No newline at end of file diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 00000000..57cfcd10 --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,57 @@ +# This is a basic workflow to help you get started with Actions + +name: app-dev + +# Controls when the workflow will run +on: + pull_request: + branches: [ "main", "classic" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + deploy: + name: Build, Deploy to S3 bucket + runs-on: [ubuntu-latest] + + strategy: + matrix: + node-version: [17.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install yarn + run: npm install --location=global yarn + + - name: Package install + run: yarn + + - name: Build + run: CI=false yarn build + + - name: Transfer to S3 for serving static + uses: jakejarvis/s3-sync-action@master + with: + args: --acl public-read --follow-symlinks --delete + env: + AWS_S3_BUCKET: app-dev.terraswap.io + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + AWS_REGION: ap-northeast-2 + SOURCE_DIR: 'build' + + - name: Invalidate Cloudfront Distribution + uses: awact/cloudfront-action@master + env: + SOURCE_PATH: '/*' + AWS_REGION: ap-northeast-2 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + DISTRIBUTION_ID: ${{ secrets.DISTRIBUTION_ID_APP_DEV }} \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..9b8dc167 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,57 @@ +# This is a basic workflow to help you get started with Actions + +name: app + +# Controls when the workflow will run +on: + push: + branches: [ "main" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + deploy: + name: Build, Deploy to S3 bucket + runs-on: [ubuntu-latest] + + strategy: + matrix: + node-version: [17.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install yarn + run: npm install --location=global yarn + + - name: Package install + run: yarn + + - name: Build + run: CI=false yarn build + + - name: Transfer to S3 for serving static + uses: jakejarvis/s3-sync-action@master + with: + args: --acl public-read --follow-symlinks --delete + env: + AWS_S3_BUCKET: app.terraswap.io + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + AWS_REGION: ap-northeast-2 + SOURCE_DIR: 'build' + + - name: Invalidate Cloudfront Distribution + uses: awact/cloudfront-action@master + env: + SOURCE_PATH: '/*' + AWS_REGION: ap-northeast-2 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_IAM_MANAGER_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_IAM_MANAGER_SECRET_ACCESS_KEY }} + DISTRIBUTION_ID: ${{ secrets.DISTRIBUTION_ID_APP }} \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..cce9d3c0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "semi": false +} diff --git a/package.json b/package.json index 9f305a1c..18a07f5e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@terra-dev/wallet-types": "^3.7.0", "@terra-money/log-finder": "^1.1.6", "@terra-money/log-finder-ruleset": "^3.0.0", - "@terra-money/react-base-components": "^2.0.0", + "@terra-money/react-base-components": "^2.1.2", "@terra-money/terra.js": "^3.1.0", "@terra-money/wallet-provider": "^3.9.2", "@testing-library/jest-dom": "^5.11.4", diff --git a/public/index.html b/public/index.html index 611b7151..0cba037a 100644 --- a/public/index.html +++ b/public/index.html @@ -3,18 +3,36 @@ - - - + + + - + - + Terraswap diff --git a/public/moonshine.json b/public/moonshine.json deleted file mode 100644 index 17ccaa67..00000000 --- a/public/moonshine.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "contracts": { - "gov": "terra12pf2c9k7m2ag2893aa6sv75nmytr9uuxzv8vgx", - "mirrorToken": "terra16y2ew6rmnehu9fn45jj55w4g37d62xgjz8zsx9", - "factory": "terra1ndzjhjszw4pp8dkkt864drgmwhc59padjfccxg", - "oracle": "terra14nh9jzg6gx3qp2jnlg5lvkmky40uxu7w9mgevz", - "mint": "terra1ycsd7mlffq2ksmqdr20y4drtf6ctw3n8fmup5g", - "staking": "terra1xxqqw7vysmh2wnq3y6hgh7d2ytmgazw62f28hh", - "tokenFactory": "terra10w3rtrs8fmgwy6rsh2xwq6x27ym4kpz3698dr4", - "collector": "terra1jmj39n0tfg6qu852fx0kr46gn4sewq6uyqyu8t" - }, - "whitelist": { - "terra16y2ew6rmnehu9fn45jj55w4g37d62xgjz8zsx9": { - "symbol": "MIR", - "name": "Mirror", - "token": "terra16y2ew6rmnehu9fn45jj55w4g37d62xgjz8zsx9", - "pair": "terra1ck0ky4ad0ecmz7sksacejxf3rek8922n2302lh", - "lpToken": "terra1xfm4k6qj3ryhpef4t4p9zgww6e3zuw6c0eqd05" - }, - "terra17c3tsywm5h95j3z7hy62mvmyjct4euly4gj3kp": { - "symbol": "mAAPL", - "name": "Apple", - "token": "terra17c3tsywm5h95j3z7hy62mvmyjct4euly4gj3kp", - "pair": "terra1d6548cmpmugndjg650k0k66fhnvkeqxavv0z07", - "lpToken": "terra1msdk05534hqupfed4v5q04f5y883ezqm0uukn7" - }, - "terra1tz0c9uy0wwaaq4p57v8qzfx0g08l3zr3zcdtgl": { - "symbol": "mGOOGL", - "name": "Google", - "token": "terra1tz0c9uy0wwaaq4p57v8qzfx0g08l3zr3zcdtgl", - "pair": "terra1t8m4cs4f32zqgsktu4pucwnlkz47dgql8crywn", - "lpToken": "terra1wxh3lw9u3k7psmvqzraxpmscmpgp329kzg834m" - }, - "terra13fkuw7gh8r0mjswj8ckyt87m84azq43q3qldmj": { - "symbol": "mTSLA", - "name": "Tesla", - "token": "terra13fkuw7gh8r0mjswj8ckyt87m84azq43q3qldmj", - "pair": "terra1uf29lrmpsmww4k3c9jcxdzet75c2pt353mx4tq", - "lpToken": "terra1zccwcq7shh4yj8j2ynecd7pyyftxlhdd77fpu3" - }, - "terra1f9pk063a99g27l5nu83pd55x6rs649s3ax7pw3": { - "symbol": "mNFLX", - "name": "Netflix", - "token": "terra1f9pk063a99g27l5nu83pd55x6rs649s3ax7pw3", - "pair": "terra1t033f2r5phvuvysu50x2lj5ctshakcf45szn49", - "lpToken": "terra1ch6d5kdenshk2zktap2s05arytpn8xhdffarvc" - }, - "terra1hu7u866jla3vgckf4sd6vjdfxzuqvzvu0ekpc9": { - "symbol": "mQQQ", - "name": "Invesco QQQ Trust", - "token": "terra1hu7u866jla3vgckf4sd6vjdfxzuqvzvu0ekpc9", - "pair": "terra19ujpfl5djdrp6w4w30vtx9cremz25gkg9nzcfa", - "lpToken": "terra1cj8rcff3djz86rarg3uw3nzgdy2trgvj5egvdl" - }, - "terra1ua295n83qqm7kncn6g704d2a3hpmtjyx7f07u7": { - "symbol": "mTWTR", - "name": "Twitter", - "token": "terra1ua295n83qqm7kncn6g704d2a3hpmtjyx7f07u7", - "pair": "terra14q8szcr0gy5pzksve5sp7e94kqqa0xlc3g2y9u", - "lpToken": "terra1wunltsvvl2gfsnpwc4hf9pdxt6tnp7rt877ny8" - }, - "terra1vekqnp3tgukt90lqfumu5467jw9jy4eewzn2fu": { - "symbol": "mBABA", - "name": "Alibaba Group Holdings Ltd ADR", - "token": "terra1vekqnp3tgukt90lqfumu5467jw9jy4eewzn2fu", - "pair": "terra1q5gyld4cjr59fdk2rjuuzs200ks28lp08fudnt", - "lpToken": "terra1vrkjzhs26qlg6863s7rcnkqlmp3ftsxfdc6l5r" - }, - "terra1cyrhd8m2hhvvrn3mrn29d4h6unzyp6deay6g2y": { - "symbol": "mIAU", - "name": "iShares Gold Trust", - "token": "terra1cyrhd8m2hhvvrn3mrn29d4h6unzyp6deay6g2y", - "pair": "terra1ygeltj9hg4tsshhx2m4et4nmhn2sqpmu2cv8qk", - "lpToken": "terra1whql3f3vukrtu3qs363vj5a67xccydjz9lpg6t" - }, - "terra17szfxhpttyp6w5p8llpqcr72yegxtaqy6uarye": { - "symbol": "mSLV", - "name": "iShares Silver Trust", - "token": "terra17szfxhpttyp6w5p8llpqcr72yegxtaqy6uarye", - "pair": "terra1vh4e69jq20tdzldc49wwuz22qe4pdr0zlwpvsg", - "lpToken": "terra1d2ujj007l2tp5r6mgp78hr0ecrtq4q9afvmlwh" - }, - "terra19sf42kkwn85dj8hzffcytvw6jx4g8g3nxfnrdu": { - "symbol": "mUSO", - "name": "United States Oil Fund, LP", - "token": "terra19sf42kkwn85dj8hzffcytvw6jx4g8g3nxfnrdu", - "pair": "terra1yde9tsacetgrdzdm56s5dng2uc53wpnyf9dyds", - "lpToken": "terra1pkv2skq9pqzpfe483dn6q2dskadrhyrqg2f5ya" - }, - "terra1kmt8vekwu4aq6l9y50n8hg9zcdzd3tqdp8lgdr": { - "symbol": "mVIXY", - "name": "ProShares VIX", - "token": "terra1kmt8vekwu4aq6l9y50n8hg9zcdzd3tqdp8lgdr", - "pair": "terra195fcntnznx4f676gf383g02yguhync2fsuk03x", - "lpToken": "terra1svhet09r7ulhyr4vs4fl6j6lnam94q6natumck" - } - } -} diff --git a/public/swap.json b/public/swap.json deleted file mode 100644 index 8628ac8d..00000000 --- a/public/swap.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "pairs": [ - { - "owner": "terra1a9azdnvp60nkajc2mwejvqlh5wj08q93zlv7qv", - "contract_addr": "terra1wlkgeumfv64avwwg87aqk8zw9n6750xzumtulh", - "lpToken": "terra1uv9fgatntfgfhq5er4k4x8xanads35t6rq9srk", - "asset_infos": [ - { - "token": { - "contract_addr": "terra1xt8efpfkyka8807t9kd29zs5mfcmt4rzhqfw8c", - "symbol": "LABS", - "name": "DELIGHTLABS" - } - }, - { - "token": { - "contract_addr": "terra18sl63stqew9kd9g0f2ngw0cdxud7236xt7ydh9", - "symbol": "DELIGHT", - "name": "DELIGHT" - } - } - ] - }, - { - "owner": "terra1a9azdnvp60nkajc2mwejvqlh5wj08q93zlv7qv", - "contract_addr": "terra12vnpp7qkyj2khqsvdtkmymtdd9zek88razqa49", - "lpToken": "terra13xgf48yukcn2r52f0jqffayxy5mweft8nq2383", - "asset_infos": [ - { - "token": { - "contract_addr": "terra1xt8efpfkyka8807t9kd29zs5mfcmt4rzhqfw8c", - "symbol": "LABS", - "name": "DELIGHTLABS" - } - }, - { - "native_token": { - "denom": "uluna", - "symbol": "Luna", - "name": "uluna" - } - } - ] - }, - { - "owner": "terra1a9azdnvp60nkajc2mwejvqlh5wj08q93zlv7qv", - "contract_addr": "terra1cvdn5wrfqmjts9qy845y9yjyhcqa39ve4gl273", - "lpToken": "terra132kvrlzltqp2frg85yps8jnelpw6auvf5g3qgu", - "asset_infos": [ - { - "token": { - "contract_addr": "terra18sl63stqew9kd9g0f2ngw0cdxud7236xt7ydh9", - "symbol": "DELIGHT", - "name": "DELIGHT" - } - }, - { - "native_token": { - "denom": "uluna", - "symbol": "Luna", - "name": "uluna" - } - } - ] - }, - { - "owner": "terra1a9azdnvp60nkajc2mwejvqlh5wj08q93zlv7qv", - "contract_addr": "terra1gs0uanree7ds9udmd4j36qg0pfcfkkhfvt3us9", - "lpToken": "terra1xe4rhy8aup4ny4gwxmtc8j854cvwpz5rhn9jsj", - "asset_infos": [ - { - "native_token": { - "denom": "ukrw", - "symbol": "KRT", - "name": "ukrw" - } - }, - { - "native_token": { - "denom": "uluna", - "symbol": "Luna", - "name": "uluna" - } - } - ] - }, - { - "owner": "terra1a9azdnvp60nkajc2mwejvqlh5wj08q93zlv7qv", - "contract_addr": "terra14uvwt4s76urudwzj6q9s42znfwngrakqvptm4x", - "lpToken": "terra1yn4z7v3cff3f7n0x5n6cxhcxvcvvrvewzcsygg", - "asset_infos": [ - { - "native_token": { - "denom": "uusd", - "symbol": "UST", - "name": "uusd" - } - }, - { - "native_token": { - "denom": "uluna", - "symbol": "Luna", - "name": "uluna" - } - } - ] - } - ] -} \ No newline at end of file diff --git a/public/tequila.json b/public/tequila.json deleted file mode 100644 index 0ec062c2..00000000 --- a/public/tequila.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "contracts": { - "gov": "terra102pll8yzs4knwvz0x20ymwauwvq46zk0adkwd8", - "mirrorToken": "terra1dw9sjfvzm9udg3uqtnrr3cph8ce3welc9ljr83", - "factory": "terra1um0l5ufa44v8nqj022tvvmyd6g4nqfy4y9ryk9", - "oracle": "terra187un3r3c59dav3y5l8n47ekp5rpgrh08ttd04x", - "mint": "terra1ptrsap5h4n0ee29qxqjpgkmhqjc4pewe8j6lxz", - "staking": "terra1wt65k5ugrpujen6r4unh3lddzr0678erny3f4q", - "tokenFactory": "terra1n0mdp2fcwuk6mkhuwtwp65upza9z5v0deawvma", - "collector": "terra18skkp9lsrv3sq0urf682nfk0cs49xdlfx3a0a8" - }, - "whitelist": { - "terra1sjw2wpak38g7595lhh95m2es78muzzaql850ss": { - "symbol": "mAAPL", - "name": "Apple", - "token": "terra1sjw2wpak38g7595lhh95m2es78muzzaql850ss", - "pair": "terra13qyg6hrztrl2gmx9l3h463pjladeup86cs8g2j", - "lpToken": "terra12dtk9pwlwyum9em2nkeefphsvg0c4ks88a2aju" - }, - "terra18xmyk8tqhrcgekxf0z69mkrna8rvgp5n8wzjx6": { - "symbol": "mGOOGL", - "name": "Google", - "token": "terra18xmyk8tqhrcgekxf0z69mkrna8rvgp5n8wzjx6", - "pair": "terra180dsn37yx3qul3qm5t9f0kd58950r663ekc3mg", - "lpToken": "terra1pnq3stlvvn597fkfwdf5ur2mffqq59an4rj88e" - }, - "terra147eejpkvujqyj02zm6gs6rmql4yjmht56hkjdj": { - "symbol": "mTSLA", - "name": "Tesla", - "token": "terra147eejpkvujqyj02zm6gs6rmql4yjmht56hkjdj", - "pair": "terra1pq5sy6dhzuvdyges2454vm7csx8y08lhjvnt64", - "lpToken": "terra1v85p94we3wp56almy3qzzpqskp0yu8amnpccey" - }, - "terra1lp6p2wuvlzv54s6a28k5mfd6spzg7mvdcfyavj": { - "symbol": "mNFLX", - "name": "Netflix", - "token": "terra1lp6p2wuvlzv54s6a28k5mfd6spzg7mvdcfyavj", - "pair": "terra1k33nulqk4mhvx3zh7dn87cv537k73elfptnela", - "lpToken": "terra1vgcyf0fmhnshl45qrrqjgjwzkvptnjdm6wcqe3" - }, - "terra10k5y7j85ajgg92grtvht30uqlrn64t2ayhexmk": { - "symbol": "mQQQ", - "name": "Invesco QQQ Trust", - "token": "terra10k5y7j85ajgg92grtvht30uqlrn64t2ayhexmk", - "pair": "terra1wvywrtd9aqsej6j74fa80umjkz0xwkuk6uan9w", - "lpToken": "terra1pju0hte482vqku5zgthdgly2j64tz6gm2s7p00" - }, - "terra1nkcss7j5umfuh0sjzmsk2l5xn2nlynumyz63wj": { - "symbol": "mTWTR", - "name": "Twitter", - "token": "terra1nkcss7j5umfuh0sjzmsk2l5xn2nlynumyz63wj", - "pair": "terra15hpqv732702rv9e34k9zcfv5f7rs3pyj5kjqmh", - "lpToken": "terra15gd9umv09spet6u7rhvqheknhcrxazvg9adjlj" - }, - "terra1x7f9dd465clkj6cu8ll4z4l9v643xhpkgx0jm3": { - "symbol": "mBABA", - "name": "Alibaba Group Holdings Ltd ADR", - "token": "terra1x7f9dd465clkj6cu8ll4z4l9v643xhpkgx0jm3", - "pair": "terra19src9qxfgaxan4st23s2hz4axq6ypkdffzn5qw", - "lpToken": "terra1vwj824y645u80l22kkqtp7qfr4n74lkhzss6s3" - }, - "terra100gxsglqfc7uz3uppet5ytl3cp03lmkcqx9njn": { - "symbol": "mIAU", - "name": "iShares Gold Trust", - "token": "terra100gxsglqfc7uz3uppet5ytl3cp03lmkcqx9njn", - "pair": "terra1djcthczd5nvhqjqdfuzzugyxuq34924kmtcgpm", - "lpToken": "terra1uk8kkm2kjs68ygyyn68kev67n0dmsfq6vspjx6" - }, - "terra1dqy7hjqx7c9qx92t308ylfgmmlq0eg9gtp5wvc": { - "symbol": "mSLV", - "name": "iShares Silver Trust", - "token": "terra1dqy7hjqx7c9qx92t308ylfgmmlq0eg9gtp5wvc", - "pair": "terra19dw9fxmcmte5w2l4m0wwfw9yngtl3gj2awmfr9", - "lpToken": "terra12z3lpeq4gvxfsftrcj9yfkmx9elwjh0xxf2fhc" - }, - "terra10rz7tjtduxam6nmaxm83ts6s7uprtraautrtwd": { - "symbol": "mUSO", - "name": "United States Oil Fund, LP", - "token": "terra10rz7tjtduxam6nmaxm83ts6s7uprtraautrtwd", - "pair": "terra13zrgavrjcffxfde7dp0uppdzw2ppjqupmrr3qk", - "lpToken": "terra153ptn9uudypurdlcsx58eg6wdxfhhe04qrw0tn" - }, - "terra1y3ja7tu658x7f0twm3vpzsf4ee2vjm9xr4n0m2": { - "symbol": "mVIXY", - "name": "ProShares VIX", - "token": "terra1y3ja7tu658x7f0twm3vpzsf4ee2vjm9xr4n0m2", - "pair": "terra16th48uswly2gt6dg4m48el9wkt42g4vlfj69vj", - "lpToken": "terra1ceamc3dpkm6f8mvkzrmx3pdt8rdmqc6w46cc5l" - } - } -} diff --git a/src/components/AssetIcon.tsx b/src/components/AssetIcon.tsx index e5c0c786..7061dc21 100644 --- a/src/components/AssetIcon.tsx +++ b/src/components/AssetIcon.tsx @@ -1,5 +1,5 @@ import { GetTokenSvg } from "helpers/token" -import React, { CSSProperties, useEffect, useState } from "react" +import { CSSProperties, useEffect, useState } from "react" import { tokenInfos } from "rest/usePairs" import styled from "styled-components" diff --git a/src/components/Badge.module.scss b/src/components/Badge.module.scss deleted file mode 100644 index 12d4e18c..00000000 --- a/src/components/Badge.module.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import "src/styles/mixins.module"; - -.badge { - $height: 21px; - @include flex; - display: inline-flex; - height: $height; - border-radius: ($height / 2); - background: fade-out(white, 0.9); - color: white; - font-size: 10px; - font-weight: 500; - min-width: 90px; -} diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx deleted file mode 100644 index a403a410..00000000 --- a/src/components/Badge.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React, { PropsWithChildren } from "react" -import classNames from "classnames" -import styles from "./Badge.module.scss" - -const Badge: React.FC> = ({ - className, - children, -}) => {children} - -export default Badge diff --git a/src/components/Button.tsx b/src/components/Button.tsx index f50f9a0c..ddf08a08 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren } from "react" +import { PropsWithChildren } from "react" import classNames from "classnames/bind" import Loading from "./Loading" import styles from "./Button.module.scss" diff --git a/src/components/Card.tsx b/src/components/Card.tsx index 9560251b..a1ba42ad 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren, ReactNode } from "react" +import { PropsWithChildren, ReactNode } from "react" import { Link } from "react-router-dom" import classNames from "classnames/bind" import CardHeader from "./CardHeader" diff --git a/src/components/Change.module.scss b/src/components/Change.module.scss deleted file mode 100644 index 5079c3ee..00000000 --- a/src/components/Change.module.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import "src/styles/mixins.module"; -@import "src/styles/variables.module"; - -.flex { - @include flex(flex-start); -} - -.change { - font-size: 12px; - - &:not(:first-child) { - margin-left: 10px; - } - - i { - margin-right: 5px; - } -} - -.up { - color: $aqua; -} - -.down { - color: $red; -} diff --git a/src/components/Change.tsx b/src/components/Change.tsx deleted file mode 100644 index 97f68328..00000000 --- a/src/components/Change.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { ReactNode } from "react" -import classNames from "classnames/bind" -import { abs, gt, gte, lt } from "../libs/math" -import { percent } from "../libs/num" -import Icon from "./Icon" -import styles from "./Change.module.scss" - -const cx = classNames.bind(styles) - -interface Props { - price?: ReactNode - className?: string - children?: string -} - -const Change = ({ price, className, children }: Props) => { - const change = children && (gte(abs(children), 0.0001) ? children : "0") - - const render = (change: string) => { - const up = gt(change, 0) - const down = lt(change, 0) - const icon = up ? "trending_up" : down ? "trending_down" : "arrow_right_alt" - return ( - - - {percent(abs(change))} - - ) - } - - return !(price || change) ? null : change ? ( - render(change) - ) : ( - - {price} - {change && render(change)} - - ) -} - -export default Change diff --git a/src/components/ChangeVersionButton.tsx b/src/components/ChangeVersionButton.tsx new file mode 100644 index 00000000..160982d0 --- /dev/null +++ b/src/components/ChangeVersionButton.tsx @@ -0,0 +1,61 @@ +import iconArrowLeft from "images/icon-arrow-left.svg" +import iconArrowLeftPrimary from "images/icon-arrow-left-primary.svg" +import styled from "styled-components" + +const Button = styled.button` + width: 100%; + height: auto; + position: relative; + background-color: transparent; + padding: 9px; + border-radius: 10px; + border: solid 1px #fff; + + box-sizing: border-box; + font-size: 14px; + font-weight: bold; + font-stretch: normal; + font-style: normal; + line-height: normal; + + letter-spacing: normal; + color: #fff; + + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + + &::before { + content: ""; + display: inline-block; + + width: 13.9px; + height: 10.4px; + display: inline-block; + + margin-right: 6.1px; + + background-image: url(${iconArrowLeft}); + background-size: contain; + background-repeat: no-repeat; + background-position: 50% 50%; + + transition: background-image 0.1s step-end; + } + + &:hover { + background-color: #ffffff; + color: #0222ba; + &::before { + background-image: url(${iconArrowLeftPrimary}); + } + } +` + +const ChangeVersionButton = () => { + return ( + + + + ) +} + +export default ChangeVersionButton diff --git a/src/components/Chart.tsx b/src/components/Chart.tsx index 6d7616ed..79da9da3 100644 --- a/src/components/Chart.tsx +++ b/src/components/Chart.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useEffect, useState } from "react" +import { useRef, useEffect, useState } from "react" import { path } from "ramda" import { debounce, merge as mergeDeep } from "lodash" import ChartJS, { diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index b8625a45..5e5768b7 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,4 +1,4 @@ -import React from "react" +import { forwardRef } from "react" import styled, { css } from "styled-components" import iconChecked from "images/icon-checked.svg" @@ -84,7 +84,7 @@ const Wrapper = styled.label` } ` -const Checkbox = React.forwardRef( +const Checkbox = forwardRef( ({ children, block, ...props }, forwardedRef) => { return ( diff --git a/src/components/Copy.tsx b/src/components/Copy.tsx index a1432783..d7874409 100644 --- a/src/components/Copy.tsx +++ b/src/components/Copy.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useRef } from "react" +import { useState, useCallback, useRef } from "react" import styled, { css } from "styled-components" import iconCopy from "images/icon-copy-outline.svg" diff --git a/src/components/Count.tsx b/src/components/Count.tsx index 9961ac25..ae934f9a 100644 --- a/src/components/Count.tsx +++ b/src/components/Count.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState, useEffect } from "react" +import { useRef, useState, useEffect } from "react" import { plus, minus, div, gt, lt } from "../libs/math" import { format, lookupSymbol } from "../libs/parse" diff --git a/src/components/DisclaimerAgreement.tsx b/src/components/DisclaimerAgreement.tsx index 4b38a06d..b69a93f8 100644 --- a/src/components/DisclaimerAgreement.tsx +++ b/src/components/DisclaimerAgreement.tsx @@ -52,6 +52,16 @@ const ModalTitle = styled.div` color: #0222ba; margin-bottom: 30px; ` + +const Content = styled.div` + border-radius: 12px; + border: solid 1px #b5b5b5; + background-color: #fff; + padding: 12px; + margin-bottom: 30px; + max-height: 115px; + overflow-y: auto; +` const Disclaimer = () => { const [disclaimerAgreed, setDisclaimerAgreed] = useState(false) @@ -71,8 +81,17 @@ const Disclaimer = () => { {}} open={() => {}}>
- Please read before using Terraswap -
+ You are accessing Terraswap + + Terraswap is a community dex. Terraswap team does not make any + financial profit from it. We built Terraswap to support the + community because we do believe our devotion makes the community + stronger. + + + Disclaimer + + Terraswap is a decentralized exchange on Terra blockchain. Trading and providing liquidity on Terraswap is at your own risk, without warranties of any kind. Please read the  @@ -85,15 +104,13 @@ const Disclaimer = () => { document  carefully and understand how Terraswap works before using it. -
-
-
- I acknowledge and agree that I am responsible for various losses of - assets by making transactions on Terraswap, including swap, - liquidity provision/withdrawal, etc. The entities involved in this - site are not liable for any damages resulting from my use of +
+
I acknowledge and agree that I am responsible for various + losses of assets by making transactions on Terraswap, including + swap, liquidity provision/withdrawal, etc. The entities involved in + this site are not liable for any damages resulting from my use of Terraswap. -
+
diff --git a/src/components/ExtLink.tsx b/src/components/ExtLink.tsx index a4588aab..781586d2 100644 --- a/src/components/ExtLink.tsx +++ b/src/components/ExtLink.tsx @@ -1,4 +1,4 @@ -import React, { AnchorHTMLAttributes } from "react" +import { AnchorHTMLAttributes } from "react" export type Props = AnchorHTMLAttributes const ExtLink = ({ children, ...attrs }: Props) => ( diff --git a/src/components/ExtLinkButton.tsx b/src/components/ExtLinkButton.tsx index a7212b03..bc2f4548 100644 --- a/src/components/ExtLinkButton.tsx +++ b/src/components/ExtLinkButton.tsx @@ -1,4 +1,3 @@ -import React from "react" import { getAttrs } from "./Button" import ExtLink, { Props as ExtLinkProps } from "./ExtLink" diff --git a/src/components/Grid.module.scss b/src/components/Grid.module.scss deleted file mode 100644 index a6f5dea1..00000000 --- a/src/components/Grid.module.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import "src/styles/mixins.module"; - -$gutter: 30px; -$margin: ($gutter / 2); - -.row { - @include flex(flex-start); - align-items: stretch; - margin: -$margin; - - > * { - flex: 1; - margin: $margin; - } - - @include mobile { - flex-direction: column; - } - - & + & { - margin-top: $margin; - } -} - -@include desktop { - .wrap { - flex-wrap: wrap; - - > * { - flex: none; - } - } - - .wrap-2 > * { - width: calc((100% / 2) - #{$gutter}); - } - - .wrap-3 > * { - width: calc((100% / 3) - #{$gutter}); - } - - .wrap-4 > * { - width: calc((100% / 4) - #{$gutter}); - } -} diff --git a/src/components/Grid.tsx b/src/components/Grid.tsx deleted file mode 100644 index 3976d9bc..00000000 --- a/src/components/Grid.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { FC, PropsWithChildren } from "react" -import classNames from "classnames/bind" -import styles from "./Grid.module.scss" - -const cx = classNames.bind(styles) - -const Grid: FC> = ({ children, wrap }) => ( -
- {children} -
-) - -export default Grid diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 6869c53e..9f3a7785 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,4 +1,3 @@ -import React from "react" import classNames from "classnames" interface Props { diff --git a/src/components/Input.tsx b/src/components/Input.tsx index f55bee6e..a46bf3af 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -1,4 +1,3 @@ -import React from "react" import styled from "styled-components" const Wrapper = styled.div` diff --git a/src/components/LatestBlock.tsx b/src/components/LatestBlock.tsx index eb6398f6..38961d57 100644 --- a/src/components/LatestBlock.tsx +++ b/src/components/LatestBlock.tsx @@ -1,5 +1,5 @@ import { useNetwork } from "hooks" -import React from "react" + import { useQuery } from "react-query" import useDashboardAPI from "rest/useDashboardAPI" import styled from "styled-components" diff --git a/src/components/List.tsx b/src/components/List.tsx index 1b8d4c55..ddbc2c46 100644 --- a/src/components/List.tsx +++ b/src/components/List.tsx @@ -1,4 +1,3 @@ -import React from "react" import styled from "styled-components" type ListProps = { diff --git a/src/components/ListCard.tsx b/src/components/ListCard.tsx index d24e1824..c7140a31 100644 --- a/src/components/ListCard.tsx +++ b/src/components/ListCard.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from "react" +import { ReactNode } from "react" import Card from "./Card" import styles from "./ListCard.module.scss" diff --git a/src/components/Progress.module.scss b/src/components/Progress.module.scss deleted file mode 100644 index 85a150dd..00000000 --- a/src/components/Progress.module.scss +++ /dev/null @@ -1,90 +0,0 @@ -@import "src/styles/mixins.module"; -@import "src/styles/variables.module"; - -.component { - user-select: none; -} - -.cursor { - cursor: crosshair; -} - -/* axis */ -$axis-height: 25px; -.axis { - position: relative; - height: $axis-height; -} - -.x { - position: absolute; - top: 0; - color: $slate; - font-size: 12px; - font-weight: 500; - height: $axis-height; - transform: translate(-50%, 0); - - &:after { - content: ""; - display: block; - width: 1px; - height: 5px; - background: $slate; - - position: absolute; - left: 50%; - bottom: 0; - } -} - -/* track */ -.track { - @include flex(flex-start, stretch); - background: $slate; - border-radius: 4px; - height: 8px; - overflow: hidden; -} - -.item { - @include transition; -} - -/* feedback */ -.feedback { - margin-top: 5px; -} - -.label { - font-size: 12px; - font-weight: 600; - text-transform: uppercase; -} - -/* feedback:ratio */ -.ratio { - @include transition; - transform: translate(-50%, 0); -} - -/* feedback:vote */ -.vote { - @include flex(space-between); -} - -.text { - text-align: center; - - &:first-child { - text-align: left; - } - - &:last-child { - text-align: right; - } -} - -.percent { - font-size: 16px; -} diff --git a/src/components/Progress.tsx b/src/components/Progress.tsx deleted file mode 100644 index 721eaafb..00000000 --- a/src/components/Progress.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React, { MouseEvent, ReactNode, useRef } from "react" -import classNames from "classnames/bind" -import { div } from "../libs/math" -import { percent } from "../libs/num" -import styles from "./Progress.module.scss" - -const cx = classNames.bind(styles) - -interface Item { - value: string - label?: string - color?: "blue" | "orange" | "red" -} - -interface Props { - data: Item[] - axis?: { x: string; label: ReactNode }[] - className?: string - onClick?: (x: string) => void - noLabel?: boolean -} - -const Progress = ({ data, axis, className, onClick, noLabel }: Props) => { - const componentRef = useRef(null!) - - const handleClick = (e: MouseEvent) => { - const { left, width } = componentRef.current.getBoundingClientRect() - const x = div(e.clientX - left, width) - onClick?.(x) - } - - return ( -
- {axis && ( -
- {axis.map(({ x, label }, index) => ( -
- {label} -
- ))} -
- )} - -
- {data.map(({ value, color }, index) => ( -
- ))} -
- - {!noLabel && ( -
- {data.map(({ value, label, color }, index) => ( -
- {label} -
- ))} -
- )} -
- ) -} - -export default Progress diff --git a/src/components/RadioButton.tsx b/src/components/RadioButton.tsx new file mode 100644 index 00000000..075d5185 --- /dev/null +++ b/src/components/RadioButton.tsx @@ -0,0 +1,55 @@ +import styled, { css } from "styled-components" + +interface RadioButtonProps { + isSelected?: boolean +} + +const RadioButton = styled.button` + width: auto; + height: auto; + position: relative; + display: inline-block; + padding: 10px; + border-radius: 21px; + border: solid 1px transparent; + + font-size: 16px; + font-weight: bold; + font-stretch: normal; + font-style: normal; + line-height: 22px; + letter-spacing: normal; + color: #ffffff; + + ${({ isSelected }) => + isSelected && + css` + border-color: #ffffff; + `} + + &::before { + content: ""; + display: inline-block; + width: 22px; + height: 22px; + vertical-align: top; + + border-radius: 50%; + background-color: #ffffff; + + border: 3px solid #ffffff; + + margin-right: 7px; + box-sizing: border-box; + font-size: 0; + line-height: 1; + + ${({ isSelected }) => + isSelected && + css` + background-color: #0222ba; + `} + } +` + +export default RadioButton diff --git a/src/components/Select.tsx b/src/components/Select.tsx index 5ed1ed48..968e9a42 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -1,4 +1,3 @@ -import React from "react" import styled from "styled-components" import iconClosed from "images/icon-dropdown-closed.svg" diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index 37c40c05..118cd033 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from "react" +import { useEffect, useMemo, useState } from "react" import { useForm } from "react-hook-form" import styles from "./Settings.module.scss" diff --git a/src/components/SocialMediaAnchor.tsx b/src/components/SocialMediaAnchor.tsx index 7dc4a02e..dad63e6f 100644 --- a/src/components/SocialMediaAnchor.tsx +++ b/src/components/SocialMediaAnchor.tsx @@ -1,4 +1,3 @@ -import React from "react" import styled from "styled-components" const Wrapper = styled.a` diff --git a/src/components/SwapPage.tsx b/src/components/SwapPage.tsx index 7fa0b3cd..53ad584e 100644 --- a/src/components/SwapPage.tsx +++ b/src/components/SwapPage.tsx @@ -1,4 +1,12 @@ -import { FC, PropsWithChildren, ReactNode } from "react" +import { NetworkInfo, useWallet } from "@terra-money/wallet-provider" +import { + FC, + PropsWithChildren, + ReactNode, + useLayoutEffect, + useRef, +} from "react" +import { useSearchParams } from "react-router-dom" import Container from "./Container" import styles from "./SwapPage.module.scss" @@ -16,6 +24,34 @@ const Page: FC> = ({ }) => { const { sm } = props + const lastNetworkRef = useRef() + const { network } = useWallet() + const [searchParams, setSearchParams] = useSearchParams() + + useLayoutEffect(() => { + const timerId = setTimeout(() => { + if ( + network && + lastNetworkRef.current && + network?.name !== lastNetworkRef.current?.name && + window.location.pathname.includes("/swap") && + searchParams && + setSearchParams + ) { + searchParams.set("from", "") + searchParams.set("to", "") + setSearchParams(searchParams, { replace: true }) + } + lastNetworkRef.current = network + }, 10) + + return () => { + clearTimeout(timerId) + } + // #112: Do not add searchParams, setSearchParams to deps for performance reasons. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [network]) + return (
{sm ? {children} : children} diff --git a/src/components/TabCard.tsx b/src/components/TabCard.tsx index 13b5856f..efd8bc34 100644 --- a/src/components/TabCard.tsx +++ b/src/components/TabCard.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useState } from "react" +import { ReactNode, useState } from "react" import classNames from "classnames" import MESSAGE from "../lang/MESSAGE.json" import Card from "./Card" diff --git a/src/components/TabView.tsx b/src/components/TabView.tsx index 69f55c96..72849b27 100644 --- a/src/components/TabView.tsx +++ b/src/components/TabView.tsx @@ -1,4 +1,4 @@ -import React, { FC, PropsWithChildren } from "react" +import { FC, Fragment, PropsWithChildren } from "react" import { Link, useLocation } from "react-router-dom" import classNames from "classnames" import Card from "./Card" @@ -79,7 +79,7 @@ const TabView: FC> = ({ )} > {side?.map((item, index) => ( - +
> = ({ {item.visible && item.component} )} - + ))}
)} diff --git a/src/components/Table.old.tsx b/src/components/Table.old.tsx deleted file mode 100644 index 2a4ea927..00000000 --- a/src/components/Table.old.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import React, { ReactNode } from "react" -import classNames from "classnames/bind" -import { path } from "ramda" -import styles from "./Table.module.scss" - -const cx = classNames.bind(styles) - -interface Table { - rows?: (record: T) => Row - columns: Column[] - dataSource: T[] -} - -interface Row { - background?: string -} - -interface Column { - key: string - title?: ReactNode - dataIndex?: string - render?: (value: any, record: T, index: number) => ReactNode - children?: Column[] - - colSpan?: number - className?: string - align?: "left" | "right" | "center" - fixed?: "left" | "right" - narrow?: string[] - border?: BorderPosition[] - bold?: boolean - width?: string | number -} - -enum BorderPosition { - LEFT = "left", - RIGHT = "right", -} - -const SEP = "." - -type DefaultRecordType = Record -function Table(props: Table) { - const { rows, columns, dataSource } = props - - const normalized = columns.reduce[]>( - (acc, { children, ...column }) => { - // Normalize nested columns below `children` - // The first child draws the left border - // The last child draws the right border. - const renderChild = (child: Column, index: number) => ({ - ...child, - key: [column.key, child.key].join(SEP), - border: !index - ? [BorderPosition.LEFT] - : index === children!.length - 1 - ? [BorderPosition.RIGHT] - : undefined, - }) - - return !children - ? [...acc, column] - : [...acc, ...children.map(renderChild)] - }, - [] - ) - - const getClassName = ({ align, fixed, narrow, border }: Column) => { - const alignClassName = `text-${align}` - const fixedClassName = `fixed-${fixed}` - const borderClassName = cx(border?.map((position) => `border-${position}`)) - const narrowClassName = cx(narrow?.map((position) => `narrow-${position}`)) - - return cx( - styles.cell, - alignClassName, - fixedClassName, - borderClassName, - narrowClassName - ) - } - - const renderColSpan = (column: Column) => { - // children: colspan attribute, border props - // No children: empty the title - const { children } = column - const colSpan = children?.length - const next = Object.assign( - { ...column, colSpan, children: undefined }, - children - ? { border: [BorderPosition.LEFT, BorderPosition.RIGHT] } - : { title: "" } - ) - - return renderTh(next) - } - - const renderTh = (column: Column): ReactNode => { - const { key, title, colSpan, width } = column - return ( - - {title ?? key} - - ) - } - - const colspan = columns.some(({ children }) => children) - return ( -
- - - {colspan && ( - {columns.map(renderColSpan)} - )} - - {normalized.map(renderTh)} - - - - {dataSource.map((record, index) => { - const renderTd = (column: Column): ReactNode => { - const { key, dataIndex, render } = column - const { className, bold, width } = column - const value = path((dataIndex ?? key).split(SEP), record) - const tdClassName = cx({ bold }, styles.td, className) - - return ( - - ) - } - - return ( - - {normalized.map(renderTd)} - - ) - })} - -
- {render?.(value, record, index) ?? value} -
-
- ) -} - -export default Table diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 587b462c..5a537be2 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react" +import { useEffect } from "react" import styled, { css } from "styled-components" import { useTable, diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index dde604f1..0bf1023c 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -1,4 +1,4 @@ -import React, { FC, PropsWithChildren } from "react" +import { FC, PropsWithChildren } from "react" import Tippy, { TippyProps } from "@tippyjs/react" import classNames from "classnames" import { isNil } from "ramda" diff --git a/src/components/UnsupportedNetworkModal.tsx b/src/components/UnsupportedNetworkModal.tsx new file mode 100644 index 00000000..4261bcd8 --- /dev/null +++ b/src/components/UnsupportedNetworkModal.tsx @@ -0,0 +1,141 @@ +import { useChainOptions } from "@terra-money/wallet-provider" +import { AVAILABLE_CHAIN_ID_LIST } from "constants/networks" +import { useNetwork } from "hooks" +import { useMemo } from "react" +import styled from "styled-components" +import Button from "./Button" +import Modal from "./Modal" + +const ModalContent = styled.div` + width: 100%; + max-width: calc(100vw - 32px); + margin: 0 auto; + border-radius: 20px; + box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.35); + background-color: #fff; + padding: 30px 0px; + color: #5c5c5c; + & > div { + position: relative; + width: 100%; + height: auto; + max-height: 80vh; + overflow-y: auto; + padding: 0 30px; + + font-size: 14px; + font-weight: normal; + font-stretch: normal; + font-style: normal; + line-height: 1.71; + letter-spacing: normal; + text-align: center; + color: #5c5c5c; + } + + @media screen and (max-width: ${({ theme }) => theme.breakpoint}) { + padding: 30px 0px; + & > div { + padding: 0 16px; + } + } +` + +const ModalTitle = styled.div` + display: block; + font-size: 20px; + font-weight: bold; + font-stretch: normal; + font-style: normal; + line-height: 1.35; + letter-spacing: normal; + text-align: center; + color: #0222ba; + margin-bottom: 30px; +` + +const UnsupportedNetworkModal: React.FC<{ isOpen?: boolean }> = ({ + isOpen = false, +}) => { + const network = useNetwork() + const chainOptions = useChainOptions() + const availableNetworks = useMemo(() => { + if (chainOptions?.walletConnectChainIds) { + const keys = Object.keys(chainOptions?.walletConnectChainIds).map(Number) + return keys + .filter((key) => + AVAILABLE_CHAIN_ID_LIST.includes( + chainOptions?.walletConnectChainIds[key]?.chainID + ) + ) + .map((key) => chainOptions?.walletConnectChainIds[key]) + } + return [] + }, [chainOptions]) + + return ( + {}} open={() => {}}> + +
+ Wrong network connection +
+ Your wallet is connected to{" "} + + {network.name}({network.chainID}) + + .
+ Please change your network setting of the wallet to +
+ {availableNetworks + .map( + (availableNetwork) => + `${availableNetwork.name}(${ + availableNetwork.chainID?.split("-")?.[0] + })` + ) + .reverse() + .join(", ")} +
+
+ + {network?.name === "classic" && ( + + )} +
+
+
+ ) +} + +export default UnsupportedNetworkModal diff --git a/src/components/Warning.tsx b/src/components/Warning.tsx index 26698cb6..438cbc12 100644 --- a/src/components/Warning.tsx +++ b/src/components/Warning.tsx @@ -1,5 +1,3 @@ -import React from "react" - import Modal from "components/Modal" import styles from "./Warning.module.scss" diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 399f3309..d2b2137c 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -10,69 +10,14 @@ import iconDocumentsLight from "images/icon-docs-primary.svg" /* terra:network */ export const FINDER = "https://finder.terra.money" -export const TERRA_STATION_EXTENSION = - "https://chrome.google.com/webstore/detail/terra-station/aiifbnbfobpmeekipheeijimdpnlpgpp" -export const XDEFI_EXTENSION = - "https://chrome.google.com/webstore/detail/xdefi-wallet/hmeobnfnfcmdkdcmlblgagmfpfboieaf" export const CHROME = "https://google.com/chrome" -/* terra:configs */ -export const BLOCK_TIME = 6650 // 6.65s - /* terraswap:unit */ -export const MIR = "MIR" -export const UUSD = "uusd" export const ULUNA = "uluna" -export const UKRW = "ukrw" -export const USDR = "usdr" -export const UMNT = "umnt" -export const UAUD = "uaud" -export const UCAD = "ucad" -export const UCHF = "uchf" -export const UCNY = "ucny" -export const UEUR = "ueur" -export const UGBP = "ugbp" -export const UHKD = "uhkd" -export const UINR = "uinr" -export const UJPY = "ujpy" -export const USGD = "usgd" -export const UTHB = "uthb" -export const UST = "UST" -export const KRT = "KRT" -export const SDT = "SDT" -export const MNT = "MNT" export const LUNA = "Luna" -export const AUT = "AUT" -export const CAT = "CAT" -export const CHT = "CHT" -export const CNT = "CNT" -export const EUT = "EUT" -export const GBT = "GBT" -export const HKT = "HKT" -export const INT = "INT" -export const JPT = "JPT" -export const SGT = "SGT" -export const THT = "THT" export const LP = "LP" -export const NATIVE_TOKENS = [ - ULUNA, - UUSD, - UKRW, - USDR, - UMNT, - UEUR, - UCNY, - UJPY, - UGBP, - UINR, - UCAD, - UCHF, - UAUD, - USGD, - UTHB, - UHKD, -] +export const NATIVE_TOKENS = [ULUNA] /* terraswap:configs */ export const DEFAULT_MAX_SPREAD = 0.5 @@ -80,20 +25,7 @@ export const MAX_MSG_LENGTH = 1024 /* network:settings */ export const TX_POLLING_INTERVAL = 1000 -export const MAX_TX_POLLING_RETRY = 20 -export const DEFAULT_EXT_NETWORK: ExtNetworkConfig = { - name: "mainnet", - chainID: "columbus-5", - fcd: "https://fcd.terra.dev", - lcd: "https://lcd.terra.dev", -} - -/* project */ -export const MEDIUM = "" -export const DISCORD = "" -export const TELEGRAM = "" -export const WECHAT = "" -export const GITHUB = "https://github.com/DELIGHT-LABS/terraswap-web-app" +export const MAX_TX_POLLING_RETRY = 35 export const socialMediaList = [ { @@ -111,7 +43,7 @@ export const socialMediaList = [ { icon: iconDiscord, iconLight: iconDiscordLight, - href: "https://discord.gg/stsqZRdy6a", + href: "https://discord.gg/nfZgjyjtQq", title: "Discord", }, { diff --git a/src/constants/mainnet-tokens.json b/src/constants/mainnet-tokens.json deleted file mode 100644 index 992c51a0..00000000 --- a/src/constants/mainnet-tokens.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"1273145497245","contract_addr":"terra1kscs6uhrqwy6rx5kuw5lwpuqvm3t6j2d6uf2lp"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1hqgzrrtsft73pjnlf7w946u3m70a99cxjjm879"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra176eej9z5upauemz7wg2q6n86472xyy836v6smx"},{"name":"loterra","symbol":"LOTA","decimals":6,"total_supply":"7000000000000","contract_addr":"terra1ez46kxtulsdv07538fh5ra5xj8l68mu8eg24vr"},{"name":"Anchor Token","symbol":"ANC","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"},{"name":"Airbnb, Inc.","symbol":"mABNB","decimals":6,"total_supply":"30865029527","contract_addr":"terra1g4x2pzmkc9z3mseewxf758rllg08z3797xly0n"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"918927714322","contract_addr":"terra15hp9pr8y4qsvqvxf3m4xeptlk7l8h60634gqec"},{"name":"Ether","symbol":"mETH","decimals":6,"total_supply":"2964367590","contract_addr":"terra1dk3g53js3034x4v5c3vavhj2738une880yu6kx"},{"name":"AMC Entertainment Holdings, Inc.","symbol":"mAMC","decimals":6,"total_supply":"86281548122","contract_addr":"terra1qelfthdanju7wavc5tq0k5r0rhsyzyyrsn09qy"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra137qvfdvlkj9vfhrctz4rlkk7lmgql7xalqlwpw"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra15gwkyepfc6xgca5t5zefzwy42uts8l2m4g40k6"},{"name":"Anchor Token","symbol":"ANC","decimals":6,"total_supply":"0","contract_addr":"terra1aqfqmal9vllc75dhqplx3zdfsyfpmx9c0q9rud"},{"name":"SPDR S\u0026P 500","symbol":"mSPY","decimals":6,"total_supply":"10379477544","contract_addr":"terra1aa00lpfexyycedfg5k2p60l9djcmw0ue5l8fhc"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra12nxvzzqv0yeh80z6eya0gcufyn36ntrkcalnjl"},{"name":"Goldman Sachs Group, Inc.","symbol":"mGS","decimals":6,"total_supply":"10125329979","contract_addr":"terra137drsu8gce5thf6jr5mxlfghw36rpljt3zj73v"},{"name":"Goat Token","symbol":"GOAT","decimals":6,"total_supply":"20000000","contract_addr":"terra1q59h4hyxvfpu2hp3v39r8rpl4wykqe7axrc9rr"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1vwvpvamj60rtnzxzr00thgtv5hplhu55jx67d6"},{"name":"Galaxy Digital Holdings Ltd","symbol":"mGLXY","decimals":6,"total_supply":"146735583294","contract_addr":"terra1l5lrxtwd98ylfy09fn866au6dp76gu8ywnudls"},{"name":"Anchor Token","symbol":"ANC","decimals":6,"total_supply":"77854710496480","contract_addr":"terra1587zn7hagaylrp22x5edz25zpqfn6szfmvtym4"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"2184634291082","contract_addr":"terra1zp3a6q6q4953cz376906g5qfmxnlg77hx3te45"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"494996575485","contract_addr":"terra1cc3enj9qgchlrj34cnzhwuclc4vl2z3jl7tkqg"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra12lvpnlphqh3q0cxp8y47e5km8k2ad5ydw5asu4"},{"name":"Bitcoin","symbol":"mBTC","decimals":6,"total_supply":"184025487","contract_addr":"terra1rhhvx8nzfrx5fufkuft06q5marfkucdqwq5sjw"},{"name":"Facebook, Inc.","symbol":"mFB","decimals":6,"total_supply":"13315048627","contract_addr":"terra1mqsjugsugfprn3cvgxsrr8akkvdxv2pzc74us7"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"64742965888551","contract_addr":"terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp"},{"name":"Anchor Token","symbol":"ANC","decimals":6,"total_supply":"77854710496480","contract_addr":"terra1ky3uafsw2kkddrhm039klksqkuwtdsfsmpc748"},{"name":"GameStop Corporation","symbol":"mGME","decimals":6,"total_supply":"12638250966","contract_addr":"terra1m6j6j9gw728n82k78s0j9kq8l5p6ne0xcc820p"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1enj2np0785hw3vt2gn2yga9y75306g6e9lq799"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"97182586417","contract_addr":"terra1csk6tc7pdmpr782w527hwhez6gfv632tyf72cp"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"61137591557","contract_addr":"terra1jsxngqasf2zynj5kyh0tgq9mj3zksa5gk35j4k"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra14xulq5g99rfmrm6qkgzmrrspvknupajdqyd92k"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1ay3729yle6u6wxj3wcm8racn50a2yq5r8vxvkx"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"610876099373","contract_addr":"terra1lvmx8fsagy70tv0fhmfzdw9h6s3sy4prz38ugf"},{"name":"Coinbase Global, Inc.","symbol":"mCOIN","decimals":6,"total_supply":"33975890762","contract_addr":"terra18wayjpyq28gd970qzgjfmsjj7dmgdk039duhph"},{"name":"iShares Gold Trust.","symbol":"mIAU","decimals":6,"total_supply":"419042567852","contract_addr":"terra10h7ry7apm55h4ez502dqdv9gr53juu85nkd4aq"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra1yrch507vhsmd9rue6q3v8pz4pe445jl09nrvz6"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"253573307008","contract_addr":"terra1vxtwu4ehgzz77mnfwrntyrmgl64qjs75mpwqaz"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra1td527f09l7lgf55fqtr0zvtx5ek0yl0fdrx574"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1gun7mcfjq965gm2jqmq2upxkeqd2lay4qrzfej"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"11896387418","contract_addr":"terra1h8arz2k547uvmpxctuwush3jzc8fun4s96qgwt"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1cczv3ck2r909w64n9rdqs3gh5gsmwumh4utz49"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra1h4hvry62zk4zh0udecqmatfg02phnyu6hq74xd"},{"name":"ProShares VIX Short-Term Futures ETF","symbol":"mVIXY","decimals":6,"total_supply":"311458810820","contract_addr":"terra19cmt6vzvhnnnfsmccaaxzy2uaj06zjktu6yzjx"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"114238790720","contract_addr":"terra1227ppwxxj3jxz8cfgq00jgnxqcny7ryenvkwj6"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"108000000","contract_addr":"terra17wgmccdu57lx09yzhnnev39srqj7msg9ky2j76"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"51817637167","contract_addr":"terra14y5affaarufk3uscy2vr6pe6w6zqf2wpjzn5sh"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1uhwhrypcnucvcc2ayt92mlky2xtatslrn7tte4"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"9546458685","contract_addr":"terra165nd2qmrtszehcfrntlplzern7zl4ahtlhd5t2"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1tthplnk67e7tvga2dh49jk6l6cn4furuuffu9x"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"144412490509","contract_addr":"terra1w7zgkcyt7y4zpct9dw8mw362ywvdlydnum2awa"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra165k229vdtpng40rhdfn3tqtqphwxeyjx5wrwxw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"322442949212","contract_addr":"terra1mtvslkm2tgsmh908dsfksnqu7r7lulh24a6knv"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"18497731492","contract_addr":"terra1cmrl4txa7cwd7cygpp4yzu7xu8g7c772els2y8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"23942211337","contract_addr":"terra1d34edutzwcz6jgecgk26mpyynqh74j3emdsnq5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1mnj6zstfk2ne0htcre9cvjv9ut0zd5t95wyagy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1481405853057","contract_addr":"terra1ekd58y58vq4gmxlzpc27dwuhw7wmms928ftuep"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"215039764113","contract_addr":"terra1ktckr8v7judrr6wkwv476pwsv8mht0zqzw2t0h"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"337648142223","contract_addr":"terra1jmauv302lfvpdfau5nhzy06q0j2f9te4hy2d07"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1f7jzky244gwy220xp7cdd0vzhu6l5ncafderaf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"671374926824","contract_addr":"terra14uaqudeylx6tegamqmygh85lfq8qg2jmg7uucc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2236067","contract_addr":"terra1079zf52uyn4hnxdrst38fvd9ga582xcjrmenw8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12awas0yfsn4r4ppzp4agqu8rp8gyw8weglpuca"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1whdv289y72n38x8sevz5erze8zys493ha2fd0a"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1n8fwsrf3qruwx99eg87dmw7x4pjc8n0a35vlef"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1043433410659","contract_addr":"terra122asauhmv083p02rhgyp7jn7kmjjm4ksexjnks"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1k5z9y8h9jr4ex63cmmlazn3kjc7mncn66xrrk4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"73550174478","contract_addr":"terra16auz7uhnuxrj2dzrynz2elthx5zpps5gs6tyln"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"7095004901207","contract_addr":"terra12dnl585uxzddjw9hw4ca694f054shgpg93cg90"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"5590606905135","contract_addr":"terra1xqeym28j9xgv0p93pwwt6qcxf9tdvf9ztfxf0w"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"92234209","contract_addr":"terra1mljg7dvzknqh3gc62emagf7hwxxg8efemennp8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1596359549698","contract_addr":"terra17dkr9rnmtmu7x4azrpupukvur2crnptyfvsrvr"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"262113745202","contract_addr":"terra1nuy34nwnsh53ygpc4xprlj263cztw7vc99leh2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"10000000","contract_addr":"terra1d5j958a4vrfmv20gddyp0gz0f6yx0kpd702qke"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"749489992628","contract_addr":"terra1stfeev27wdf7er2uja34gsmrv58yv397dlxmyn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2461080683139","contract_addr":"terra1ndlx5ndkknvmgj6s5ggmdlhjjsz0w6wrnwn5cf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra17tlyml4tq2hw922aq2dq4dhnjcu296mlkgrx6n"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"191475092293","contract_addr":"terra17smg3rl9vdpawwpe7ex4ea4xm6q038gp2chge5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"446195093252","contract_addr":"terra1mwu3cqzvhygqg7vrsa6kfstgg9d6yzkgs6yy3t"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10l54yyxus354jl80v57npylas00ktj7vpedml7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"228918281","contract_addr":"terra1ptsj2ufnvp5nv5lf8gtxek7c44rlztppedepfu"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"7753492444296","contract_addr":"terra17gjf2zehfvnyjtdgua9p9ygquk6gukxe7ucgwh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"6695795783","contract_addr":"terra1jl4vkz3fllvj6fchnj2trrm9argtqxq6335ews"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"65823250792025","contract_addr":"terra1gecs98vcuktyfkrve9czrpgtg0m3aq586x6gzm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"400430076786","contract_addr":"terra1ygazp9w7tx64rkx5wmevszu38y5cpg6h3fk86e"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ungyyyachxaszce53zstctel0mpzactmtz8hdp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"894427190","contract_addr":"terra1tmw02ugjulhezj868pu4s6mhlmshlez7thzane"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2650535128213","contract_addr":"terra178cf7xf4r9d3z03tj3pftewmhx0x2p77s0k6yh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra16ejsp5mhav3kppkj7w438spp0eawknsj0afhvx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"198881371783","contract_addr":"terra1falkl6jy4087h4z567y2l59defm9acmwcs70ts"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1dmuw5wyluxe6hf85x7waepwuqjgs2460fmj8qn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"668257390803","contract_addr":"terra16j09nh806vaql0wujw8ktmvdj7ph8h09ltjs2r"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xxracarga8mf8yadf8s25hekr4kd92l3wr35vm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1284985627464","contract_addr":"terra1fc5a5gsxatjey9syq93c2n3xq90n06t60nkj6l"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"4413524993","contract_addr":"terra1t4xype7nzjxrzttuwuyh9sglwaaeszr8l78u6e"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18qgqfp2pay886vakll5duudytylazyy9eh89yq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jl875nm4p2z4jgapz6al2h74ug0fpf59n7pfjg"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"193107142100","contract_addr":"terra1q7m2qsj3nzlz5ng25z5q5w5qcqldclfe3ljup9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"198711968230","contract_addr":"terra1jh2dh4g65hptsrwjv53nhsnkwlw8jdrxaxrca0"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"130827746515","contract_addr":"terra1azk43zydh3sdxelg3h4csv4a4uef7fmjy0hu20"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1y6x3mh07l8xdpxap7xw2u5pclrenjaulpcfh36"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1m4q5lr2s3j5eylf2jq06d8vw0au3trgdadezfc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1283mf36gl6zks6yxr50mc5cvzvg26qg50mq74s"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"204412760203","contract_addr":"terra1jqqegd35rg2gjde54adpj3t6ecu0khfeaarzy9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10zkfrqvgqvsh026ljcswe59lwh88yc5v43yc9q"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1583818363763","contract_addr":"terra1utf3tm35qk6fkft7ltcnscwml737vfz7xghwn5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"597053337152","contract_addr":"terra1pjgzke6h5v4nz978z3a92gqajwhn8yyh5kv4zv"}] \ No newline at end of file diff --git a/src/constants/networks.ts b/src/constants/networks.ts index 7f94b0e8..9dbec945 100644 --- a/src/constants/networks.ts +++ b/src/constants/networks.ts @@ -1,47 +1,40 @@ -import { NetworkInfo } from "@terra-dev/wallet-types" - export enum NetworkKey { MAINNET = "mainnet", TESTNET = "testnet", } -type MirrorNetworkInfo = NetworkInfo & NetworkConfig -const networks: Record = { +interface TerraswapNetwork { + factory: string + service: string + dashboard: string | undefined + router: string + fee: { + gasPrice: string + amount: string + gas: string + } +} + +export const AVAILABLE_CHAIN_ID_LIST = ["phoenix-1", "pisco-1"] + +const terraswapNetworks: Record = { mainnet: { - name: "mainnet", - chainID: "columbus-5", - lcd: "https://lcd.terra.dev", - fcd: "https://fcd.terra.dev", - id: "columbus-5", - contract: "/tequila.json", - swap: "/swap.json", - mantle: "https://fcd.terra.dev/", - stats: "https://fcd.terra.dev/", - fee: { gasPrice: "0.00506", amount: "1518", gas: "2000000" }, // 0.000500 UST - factory: "terra1ulgw0td86nvs4wtpsc80thv6xelk76ut7a7apj", + factory: "terra1466nf3zuxpya8q9emxukd7vftaf6h4psr0a07srl5zw74zh84yjqxl5qul", service: process.env.REACT_APP_MAINNET_SERVICE_URL || "https://api.terraswap.io/", dashboard: process.env.REACT_APP_MAINNET_DASHBOARD_URL, - router: "terra19qx5xe6q9ll4w0890ux7lv2p4mf3csd4qvt3ex", + router: "terra13ehuhysn5mqjeaheeuew2gjs785f6k7jm8vfsqg3jhtpkwppcmzqcu7chk", + fee: { gasPrice: "0.15", amount: "1518", gas: "500000" }, }, testnet: { - name: "testnet", - chainID: "bombay-12", - lcd: "https://bombay-lcd.terra.dev", - fcd: "https://bombay-fcd.terra.dev", - id: "bombay-12", - contract: "/tequila.json", - swap: "/swap.json", - mantle: "https://bombay-mantle.terra.dev/", - stats: "https://bombay-fcd.terra.dev/", - fee: { gasPrice: "0.00506", amount: "1518", gas: "2000000" }, // 0.050000 UST - factory: "terra18qpjm4zkvqnpjpw0zn0tdr8gdzvt8au35v45xf", + factory: "terra1jha5avc92uerwp9qzx3flvwnyxs3zax2rrm6jkcedy2qvzwd2k7qk7yxcl", service: process.env.REACT_APP_TESTNET_SERVICE_URL || - "https://api-bombay.terraswap.io/", + "https://api-pisco.terraswap.io/", dashboard: process.env.REACT_APP_TESTNET_DASHBOARD_URL, - router: "terra14z80rwpd0alzj4xdtgqdmcqt9wd9xj5ffd60wp", + router: "terra1xp6xe6uwqrspumrkazdg90876ns4h78yw03vfxghhcy03yexcrcsdaqvc8", + fee: { gasPrice: "0.15", amount: "1518", gas: "500000" }, }, } -export default networks +export default terraswapNetworks diff --git a/src/constants/terraswap.json b/src/constants/terraswap.json deleted file mode 100644 index cb94f0ba..00000000 --- a/src/constants/terraswap.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "blacklist": [ - { - "contract_addr": "terra137qvfdvlkj9vfhrctz4rlkk7lmgql7xalqlwpw", - "comment": "dummy MIR" - }, - { - "contract_addr": "terra1h4hvry62zk4zh0udecqmatfg02phnyu6hq74xd", - "comment": "dummy MIR" - }, - { - "contract_addr": "terra1vwvpvamj60rtnzxzr00thgtv5hplhu55jx67d6", - "comment": "dummy mAAPL" - }, - { - "contract_addr": "terra1gun7mcfjq965gm2jqmq2upxkeqd2lay4qrzfej", - "comment": "dummy mTWTR" - }, - { - "contract_addr": "terra12lvpnlphqh3q0cxp8y47e5km8k2ad5ydw5asu4", - "comment": "dummy mIAU" - }, - { - "contract_addr": "terra1tthplnk67e7tvga2dh49jk6l6cn4furuuffu9x", - "comment": "dummy mAMZN" - }, - { - "contract_addr": "terra1yrch507vhsmd9rue6q3v8pz4pe445jl09nrvz6", - "comment": "dummy mMSFT" - }, - { - "contract_addr": "terra1uhwhrypcnucvcc2ayt92mlky2xtatslrn7tte4", - "comment": "dummy mVIXY" - }, - { - "contract_addr": "terra1td527f09l7lgf55fqtr0zvtx5ek0yl0fdrx574", - "comment": "dummy mSLV" - }, - { - "contract_addr": "terra14xulq5g99rfmrm6qkgzmrrspvknupajdqyd92k", - "comment": "dummy mBABA" - }, - { - "contract_addr": "terra176eej9z5upauemz7wg2q6n86472xyy836v6smx", - "comment": "dummy mTSLA" - }, - { - "contract_addr": "terra1cczv3ck2r909w64n9rdqs3gh5gsmwumh4utz49", - "comment": "dummy mNFLX" - }, - { - "contract_addr": "terra1enj2np0785hw3vt2gn2yga9y75306g6e9lq799", - "comment": "dummy mQQQ" - }, - { - "contract_addr": "terra1ay3729yle6u6wxj3wcm8racn50a2yq5r8vxvkx", - "comment": "dummy mUSO" - }, - { - "contract_addr": "terra1hqgzrrtsft73pjnlf7w946u3m70a99cxjjm879", - "comment": "dummy mGOOGL" - }, - { - "contract_addr": "terra17wgmccdu57lx09yzhnnev39srqj7msg9ky2j76", - "comment": "dummy BLUNA" - }, - { - "contract_addr": "terra1ky3uafsw2kkddrhm039klksqkuwtdsfsmpc748", - "comment": "dummy ANC" - }, - { - "contract_addr": "terra1587zn7hagaylrp22x5edz25zpqfn6szfmvtym4", - "comment": "dummy ANC" - }, - { - "contract_addr": "terra1zp3a6q6q4953cz376906g5qfmxnlg77hx3te45", - "comment": "delisted mVIXY" - }, - { - "contract_addr": "terra15hp9pr8y4qsvqvxf3m4xeptlk7l8h60634gqec", - "comment": "delisted mIAU" - }, - { - "contract_addr": "terra14f7u8z4eqpxcrp4xr6knhgfp5n4h68nwy3yzg5", - "comment": "delisted DKWON" - } - ] -} diff --git a/src/constants/testnet-tokens.json b/src/constants/testnet-tokens.json deleted file mode 100644 index d471e879..00000000 --- a/src/constants/testnet-tokens.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1qkzyt2xgy54yctmrfgak0xgqukfycexmu62v4a"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra10llyp6v3j3her8u3ce66ragytu45kcmd9asj3u"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"24634722946","contract_addr":"terra16vfxm98rxlc8erj4g0sj5932dvylgmdufnugk0"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra1lkqp5j4mamh9ys8fn47vqlpxjxc8upqadt8l0k"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1184925000000000","contract_addr":"terra1tvgdtgdd2z2u5dyrx4dva29u6hlk4s27qhnldf"},{"name":"Goldman Sachs Group Inc.","symbol":"mGS","decimals":6,"total_supply":"577093065","contract_addr":"terra13myzfjdmvqkama2tt3v5f7quh75rv78w8kq6u6"},{"name":"T-METAL","symbol":"METAL","total_supply":"1248","contract_addr":"terra1cg3awp87rs70f92k5k2jwdxnhkpjqznvj6tgew"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra13mnaluqv045j5mrm3zx423x54k9fnvkqrmh5n4"},{"name":"LoTerra","symbol":"LOTA","decimals":6,"total_supply":"7000000000000","contract_addr":"terra15zx3xekhcur8jckvn3dz59t65dh9wmu86yh30e"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1hd4sxrakkyw6lt3wzt6afxekal5txg66ham9ks"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1arqnsndtt2yl9p3qgnsm97sl0es6lymqluepn5"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1lvd6rxdl09wc5za3d64ayghmcl32rghryn05g3"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1ypshk3spfnfgshnzps55kxmgup99ahqeav8afe"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"20328396","contract_addr":"terra1v0kd60lksznk482yh6yr8gu4ehfx298sq58w7y"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra1kl955eeuhwzvausac2ksq7tgezuccrdq3kxjc3"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1skm7tslzqjekcp9ma6cjldwzdfx9u59f7eglt5"},{"name":"Nebula Token","symbol":"NEB","decimals":6,"total_supply":"1010000000000","contract_addr":"terra1qvs35aqv7nu2wc0xtg7g9364dukg4p6wfk3z5j"},{"name":"WVS Financial Corp.","symbol":"mWVFC","decimals":6,"total_supply":"2527715","contract_addr":"terra18py95akdje8q8aaukhx65dplh9342m0j884wt4"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1069406250000000","contract_addr":"terra12g7jawefcedclxssxv9a0nn8mey66hz9agzc7u"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1cvqcycs795nlt8ate3ec2vy366dzlfarcp8nf7"},{"name":"Rackspace Technology, Inc.","symbol":"mRXT","decimals":6,"total_supply":"687153309","contract_addr":"terra1hvmzhnhxnyhjfnctntnn49a35w6hvygmxvjt7q"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra1vnna49gm5h42vkuygrdwtfqza062g9ma69ye4y"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1010000","contract_addr":"terra1jhct7u9j6n9s049ueaz9l8q9r997n0vym3xl94"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"69820522","contract_addr":"terra1k5rz6hh83zdufxgca22r0tygtdp8kx07g3yqs7"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra18dwmqy6l88wx7qfdqyyrjm9rcju829qljm2q53"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra10wmp0qpchz4qhr3j45fsp6s6z9qj3eg3gk87ah"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"12545049198","contract_addr":"terra15dr4ah3kha68kam7a907pje9w6z2lpjpnrkd06"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"74993862351","contract_addr":"terra19dl29dpykvzej8rg86mjqg8h63s9cqvkknpclr"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1g3j6ak8df790u0fr24c8767d7zz7ncjwkzdcsn"},{"name":"SPDR S\u0026P 500","symbol":"mSPY","decimals":6,"total_supply":"5703828","contract_addr":"terra15t9afkpj0wnh8m74n8n2f8tspkn7r65vnru45s"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"518374125","contract_addr":"terra1y05wu4hsdzshsq9vtug2ttavtql6dcfrl0yv7s"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1h54f8khgy0wftp8fl3uvfn4x5h4gpuuetjs74m"},{"name":"Minnor","symbol":"MIN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1mhjjjva6z2w90j03u3vud0l9sususxyzf5kkca"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra1l00dnru2g7nj7uc9ywadexdee24ss8xl030ze6"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"253166323993","contract_addr":"terra1pm4d64dlngwuxh8a2rmkx56lrgq795vx4g0u9g"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra16d96cpt808nnd2y7zx662zalqwadgk228af060"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1ccdcw6yw6jvxajazwzcjns4qsxv8auahkyck4n"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1cxkjdq9pf0e5u7fqthwxth3qhfy6e9xrhfkgep"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1pcx2te895u2rn66hvveg7nj4yvm8w837d9f0ya"},{"name":"LUNA","symbol":"mLUNA","decimals":6,"total_supply":"0","contract_addr":"terra1rpyd8z86acm7ykrh09ljajeq2d8k4nhktmpxs7"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1c8ae0frl9ace3nyhsl0shntrmy3ladke3h58vy"},{"name":"Nebula Token","symbol":"NEB","decimals":6,"total_supply":"1010000000000","contract_addr":"terra1hetlf94v09r7h4s8h7kxcpr9sejnxa73m0apmj"},{"name":"loterra","symbol":"LOTA","decimals":6,"total_supply":"7000000000000","contract_addr":"terra1v000amr8a59r88p33ec2kk9xqe047g7zzqqaf4"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1s4ev73yfw68ma2ud0hr5q40gkcalsvv9f82v4t"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1nzcqamxze73n39sg8l3763p0qn23cqdcpzq6tz"},{"name":"Pasta","symbol":"mPasta","decimals":6,"total_supply":"0","contract_addr":"terra162rlcxlq823elvnn08gvtr5mvl3nnfvga20hch"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra17vhda4emlzvhp57tuj0mqf7s65zqxnve9hg45h"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1vfshjsh7c2ly02y8d3yg63qwfv3ut7ekh2vewd"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"193528320","contract_addr":"terra10q9sksr0qy6ztz85yuyz65mndegwzlh3h706py"},{"name":"Kansas City Southern","symbol":"mKSU","decimals":6,"total_supply":"8821070","contract_addr":"terra1374w7fkm7tqhd9dt2r5shjk8ly2kum443uennt"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1sev0jhtml6c08m6kd4mfadrhk5fuq0pqxsvxxn"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra15npkjas0uwetnndgz8ek8vxc7a5gyudn30lnul"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1r75jkxzkupa5gezujlua07v5kdymvul2jzlxth"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"301103723","contract_addr":"terra1wjvwjuhkq99vh0wvxpx6ux0qj036mfsanlm34v"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1a83cefe7kkas5zy7d38fsjhxk03x0nnj6jjgdg"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"99999682","contract_addr":"terra1rk4kstfxvpwd3vh6ygy3r3uf72cllrvnsuj9qh"},{"name":"ProShares VIX Short-Term Futures ETF","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra18gphn8r437p2xmjpw7a79hgsglf5y4t0x7s5ee"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1wsyxfwtgtt2x5xw8jpqhu294q8ztj3y2p7hz00"},{"name":"Minnor","symbol":"MIN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1jqpw0mvw0jwmt70we577h8sseuyl97p2rp6euv"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1jhehx3v3jfg0dvut262thqd3m0efgr7gmgwunr"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1cdr8z58ywafg2wm23r4prqgp5d3hw2s8ycsmkw"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"993036103","contract_addr":"terra1qg9ugndl25567u03jrr79xur2yk9d632fke3h2"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra188rvcgcfluw8jm3sk3zu7xl3yj80chuhrkc4ne"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"4205662641644","contract_addr":"terra1u0t35drzyy0mujj8rkdyzhe264uls4ug3wdp3x"},{"name":"Test Anchor","symbol":"TANC","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1s7ls7jkgsakprtf5mujqns42mfcmpjdv7fkw6f"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1e4hwc0l3t6r528wfvcfvmzrj2zjkvt0r72tjk4"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra16lxwskn7d6c6ajns23d7apm6d6l79t7e8mnsc5"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1pgt2ag4cn3kuhhl3s7v2nxhz36g9vue07s3jc8"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"99999999","contract_addr":"terra1qdp36cxzkddw8s88wyw2sdpmxgvhld5ar4m5mr"},{"name":"Facebook Inc.","symbol":"mFB","decimals":6,"total_supply":"1114599866","contract_addr":"terra14gq9wj0tt6vu0m4ec2tkkv4ln3qrtl58lgdl2c"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1001000","contract_addr":"terra1746w2ttpr40g5ug5ext8w88vfpjdwy2qwze4f3"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1069406250000000","contract_addr":"terra1j864ka0v0k2cwjfd6endmu5p56tc0kuh3j7tjf"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1d04ukmdp27qd5e0sp4mxpg8nqqjax5605tx7u2"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra149elumdmwxmhpy7kxqj2q04wgxkzvqk7jq08a2"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1usj4gu0jnlv39esz864j3zvqd3vehfxvf5f3lu"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1hqtp6zelne5r9ecvlnm7j6w2v2z9pj2gsmjq7d"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1184925000000000","contract_addr":"terra160tzvz7f4gahqjpeekzyuydqxznmmggxhgpg2q"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1069406250000000","contract_addr":"terra1r8g30z8t6zlcc6fe5ekmer06nfperquzax5ky8"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra13j9l8wctu2cckquc0hj2s5ghmvms3d9q7mf40m"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1vpeughsvjyzsajhue366l977rff3ka0vtrf2p6"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1184925000000000","contract_addr":"terra1p3r9228afgc3j06r8xnf579mvhucuw592q8xfw"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1z6fj8f5mgkw6lgev9qfkcvs6c8d9a9hpa0u07f"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra18yn9pe87z6h6f9etv576040r84ge9tsxf97drj"},{"name":"Spectrum Token","symbol":"SPEC","decimals":6,"total_supply":"584913330000","contract_addr":"terra1w4asn68f9u6lmptkqyfxhnred48rkck5hr7w6w"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1l9kfynk9d29epv733jlwxjrhtzas780yu93jhx"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1069406250000000","contract_addr":"terra16h6pqmq2he2azst4ecc3y9dnk80j9raa8rzx00"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra12p7fpf6qlxs9nmh9ea8lg2ydaleh5hzeta4qqg"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"55301587466","contract_addr":"terra1fdkfhgk433tar72t4edh6p6y9rmjulzc83ljuw"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra123ln3sheuy9rzu7ej4krdezaf3guvnrar2776y"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1jtcu0yjzyjencuw3avr2kgeanwgdkcu395umau"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1lzjm4rf37ckmwxs4yfy2qehl4y7778v6u2lsqr"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra1h5qfw9hu2lsapm2vkmhrf8sdz2zt6mja47uwzp"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1lgh3xvnf8khxcwjfe3njm856e5m525w8k2uept"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"29999977","contract_addr":"terra19re2s49qgs3uc0fegfaxx8yqzlyl0f8r725qrs"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1tf94wlcykx3zgm49nkvez3rgpfqf3sj2ua90hh"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1lh24uffayr2z76q0exq9wfdlym5yzzkwf8lvfs"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1s9sc8wv066t2xeeq78d5l7m8ydse5m79xnmvq2"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1069406250000000","contract_addr":"terra14742lckpu6pf6zsgntxw5sh2vrrgz365eycyjl"},{"name":"Bitcoin","symbol":"mBTC","decimals":6,"total_supply":"61857989","contract_addr":"terra1csr22xvxs6r3gkjsl7pmjkmpt39mwjsrm0e2r8"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"24663393620","contract_addr":"terra1ax7mhqahj6vcqnnl675nqq2g9wghzuecy923vy"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"7590539448","contract_addr":"terra18yx7ff8knc98p07pdkhm3u36wufaeacv47fuha"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1txhlkuamu2kejx8e2stz6tzyamfudpdasxn69j"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra106kvg2adz4fljfgasu3u3zgh5fksz5w5vxfawd"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"6709667055","contract_addr":"terra1nslem9lgwx53rvgqwd8hgq7pepsry6yr3wsen4"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"15026203","contract_addr":"terra1tgmnj654p4nlcvfny7cm65v3kn5pgu8tx6lnpe"},{"name":"T-METAL","symbol":"METAL","total_supply":"1246","contract_addr":"terra1jr9s6cx4j637fctkvglrclvrr824vu3r2rrvj7"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"1184925000000000","contract_addr":"terra135uup8xwt6fec2jc664mcy0xnqjjh4y3efsqrh"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1cc069qehvzq6rf7vatag4scqhmt7vmhkegfnhk"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"0","contract_addr":"terra1ednh5l56hjnndzg6gevxj5swh4jrhd9d0nsghn"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1yv4pkds4tz5k2j7wuenat5f567ahq0lpt69ayy"},{"name":"FelixToken","symbol":"FXT","decimals":6,"total_supply":"100000000000000000","contract_addr":"terra12sfw99qz7x6kplnsef4rdt9d5rxacg96z00sla"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1scmzh4cdrgsepuuxt062p4yemtw5wct4ua6ksd"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1n2tledf4lumk848e5hvx9su7rhpwk85d5pl8lj"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra19pjcetzltn95kk5klx5sruc3ll4jex6hxt2xtu"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1ddj742e7rdpqwc2hwczj0hmqkxzuga5h2uryra"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1d44txf73p0r8t2e8gjjzmw2zrd6ww0708c9y72"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra1w6vpxq0jfut73jv2jm9q8guv5hc934458avvtg"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1snflckl9exsq4p64enxsp5jdtnpvntvp3eyv6z"},{"name":"Spectrum token","symbol":"SPEC","decimals":6,"total_supply":"90000000000","contract_addr":"terra10d83vna7dzhnwaujvmpmljd3ayatt5x2hpz7vl"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1e34eft9euddhl6h9cj9aha5pqceuwuheefq630"},{"name":"Testla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra16d4v3m45n52r0fxmjqh359ak7pdes8t3ty3v9s"},{"name":"SPCE","symbol":"SPCE","decimals":6,"total_supply":"0","contract_addr":"terra1ycywgd3hxrhr6tey45nxpjpvu338gr8hv32wxa"},{"name":"MARS MEDAL","symbol":"MEDAL","total_supply":"1248","contract_addr":"terra1t7xsmj8gdlgtyvrc2m4uqkcju6ca2hhruxm6v4"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1drh4wd9a3jzzlmlhftq9p0h0zzmt22qu55jn7g"},{"name":"WVS Financial Corp.","symbol":"mWVFC","decimals":6,"total_supply":"7876843","contract_addr":"terra1090l5p5v794dpyzr07da72cyexhuc4zag5cuer"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra13h06tm74q4ssxgae703tn7rkaccjgg9gyxpyh9"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"99999999","contract_addr":"terra17qm6jss8nq36cazclyvhz5j5kuc8nk8ygwcnps"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"133662460344","contract_addr":"terra1z0k7nx0vl85hwpv3e3hu2cyfkwq07fl7nqchvd"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1d9dvczw7ae02mj98p6j7d679400g9w7pzvjvjn"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"35775265989","contract_addr":"terra1fucmfp8x4mpzsydjaxyv26hrkdg4vpdzdvf647"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1u3r9pdj9v5tc0gpyhu9gaxlwjykpzs84mupwaq"},{"name":"MARS MEDAL","symbol":"MEDAL","total_supply":"748","contract_addr":"terra12v3936a8urd2kfnne3r07r9gqlwucd6hhgtymu"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"11000059","contract_addr":"terra136mhfksvw2ke9ye0arne7c2htfrmtfsgtsl82q"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra15kmyqtapwhulmenggvk7kgrwrspsxlz73tl6dz"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1gsa3lf882ywcu42d97zp5xd0rna2ds4ydm6nwx"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1zel5urcdtfhce06a8tuqrna24hz0s4rnxephet"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra12xfs4pm79a23e50vtz9mec6nrs2jytl752szjs"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1hl0xsxj4rkde3jf4q9hmvpjr3clrah6dt5cfgg"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1nuy5968pdy48k4anf00cqz80z37ldfxgg6mere"},{"name":"Tony","symbol":"mTONY","decimals":6,"total_supply":"500000000","contract_addr":"terra1juk7luesd8ese54j0lt9mya90ttpj87t4hvm0l"},{"name":"Apple","symbol":"mAPPL","decimals":6,"total_supply":"10009269","contract_addr":"terra1ecs880ztcdajhp9rz3wqklusfmj45ecernhnnh"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra1cp3kzg68mpl6gkcgm40zdmdrltekg58njz5608"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"0","contract_addr":"terra1rcta3ljhw3skaqeq9h6luqasg2g37urhn53z7u"},{"name":"Nebula Token","symbol":"NEB","decimals":6,"total_supply":"1010000000000","contract_addr":"terra1spjvhvw2ak3k2j0ejlxm3v0my3e84vjw20pj2t"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra10llyp6v3j3her8u3ce66ragytu45kcmd9asj3u"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1nzqaa6r4ggep9c6fqr7m8u8zjhd4dxmyks5c9r"},{"name":"Walt Disney Co.","symbol":"mDIS","decimals":6,"total_supply":"0","contract_addr":"terra18rywptlr28ut7mmglzkcjshkq32w50w4tnqxq5"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1800p00qlxh0nmt0r0u9hv7m4lg042fnafng2t6"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"105232814","contract_addr":"terra15e990g3huu0ayfneja43lpvec6hlygmpjrqs2u"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1vdt37939gsw2dc4aut035uyw9znwgnprmnxydg"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1szvx764vns67q6tae7qrfjsd62vc4dhx527qks"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"51157103","contract_addr":"terra1nff6yrcf3dnq57fn0c56ue8l86fs5eaf0l7uyh"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1ngqn2dx4ntkrpysj2mdyhmuzmsusqtdutzr5sq"},{"name":"Nebula Token","symbol":"NEB","decimals":6,"total_supply":"1010000000000","contract_addr":"terra1r63md5gt496wtwh84rfndypq0a37a7dh6cxcgy"},{"name":"Ethereum","symbol":"mETH","decimals":6,"total_supply":"596796669","contract_addr":"terra1ys4dwwzaenjg2gy02mslmc96f267xvpsjat7gx"},{"name":"Microsoft Corporation","symbol":"mMSFT","decimals":6,"total_supply":"10587277360","contract_addr":"terra12s2h8vlztjwu440khpc0063p34vm7nhu25w4p9"},{"name":"Spectrum token","symbol":"SPEC","decimals":6,"total_supply":"370575000000000","contract_addr":"terra17aelzvypafaqwuz9tlqlvr7c2xxa86g7r5rdp7"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1rs0a9ptzhyx4mdd0ryhv04patra835zq028x5s"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"2566053012","contract_addr":"terra1djnlav60utj06kk9dl7defsv8xql5qpryzvm3h"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1svkepv3lslp6mm07jlkrf8z70jgr4ketxtkxxa"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1l2fzldtvmv0n5cm0q67epkq80wqlt2taaxtmz2"},{"name":"iShares Gold Trust.","symbol":"mIAU","decimals":6,"total_supply":"999708","contract_addr":"terra1p50j2k5vyw3q2tgywqvxyz59z8csh9p7x8dk5m"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra18fnzfg288g38l2vx02vs9ll72n9adp2g7f6xls"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra173z47rsrq9h6wh5qnlq67smjd2lf9hw26w6ewj"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"216918503668","contract_addr":"terra1wq9f8p8f7gldztpdc4v3awngupfkap8wpxhtjr"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1ddaxjsa26g9407nks6q26hhmwjp4vum5eu5q32"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"69820522","contract_addr":"terra1k5rz6hh83zdufxgca22r0tygtdp8kx07g3yqs7"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra10ucqxd5sjf5mqal9jwzwdmvr3m06jjfzt8s7aq"},{"name":"Apple","symbol":"mTONY","decimals":6,"total_supply":"0","contract_addr":"terra17jlnr5kmteztquz5wh23z94v3npc9e09w83xtv"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000","contract_addr":"terra1qfrasf2ajaynut6qlfdrgts4dwp854e5ess2gd"},{"name":"Larimar Therapeutics, Inc.","symbol":"mLRMR","decimals":6,"total_supply":"588488","contract_addr":"terra19jdmle3zl99gugmptx8auckc9c2xw7nspyxjvx"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1dv0dhlruq4v9jdrxwnq3d6pyzyl9dlt0z45vhy"},{"name":"BASKET","symbol":"BSK","decimals":6,"total_supply":"0","contract_addr":"terra1kg4zr0ug0sweddthxkvt9ef3z80fneaft8rl25"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1hszny9ydf8jarzgk99rajrdd876fm5fmq7d524"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra1zkvqqmpya7kt3ng59yd3pesm22zt2cwp7extl8"},{"name":"BASKET","symbol":"BSK","decimals":6,"total_supply":"0","contract_addr":"terra109clnl2jyqq38m5n40u9jv2gpj5xz92e6tqmq4"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1c93csg8l5u8cc5njkwy6pysytjfapfpv769pfn"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1lfafvz9mkke8xmlt97j06z0ahjksncmeeyxg8p"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra184t86f5ds36rx0fzt4h9wrwu06z9u60mycrenz"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1xrtjmj6dq9m02xq0ky3rl28ujhd0n49vgmn9jw"},{"name":"Google","symbol":"mGOOGL","decimals":6,"total_supply":"0","contract_addr":"terra1j8auu07yyd7hmex9nfz52t0n9amurs6dktvvls"},{"name":"AMC Entertainment Holdings Inc.","symbol":"mAMC","decimals":6,"total_supply":"22802058890","contract_addr":"terra1zeyfhurlrun6sgytqfue555e6vw2ndxt2j7jhd"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1fdjeclqtglyxvhlscya0u6uvhn32qkuyhtlvm6"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"113895981","contract_addr":"terra1ntzes35xr0gtexgkg3v2tt599w7eda4nrtxe4v"},{"name":"iShares Gold Trust","symbol":"mIAU","decimals":6,"total_supply":"0","contract_addr":"terra1hvtvtwwefwylslnlffverlqz6nfssu3l068n2t"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1001000","contract_addr":"terra1za52dyl5y622sskwps25r9q9v8sfhy5nzhseg3"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1pl7w5maxktma63aefj4dsuq2xjmttxvjgtpfp6"},{"name":"Mirror","symbol":"MIR","decimals":6,"total_supply":"370575000000000","contract_addr":"terra18zce6004w49yh67m2mvkrvsz9vgmt23tq7sqa4"},{"name":"BASKET","symbol":"BSK","decimals":6,"total_supply":"0","contract_addr":"terra190l7g0ptq09wfywrp257pwhdqkh5fwuxdt80ec"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra19fcy5yttpx3frg7qw38fuyc2j9uv3zlqmf9sdl"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1ny50ykj90n9ahzqdgxp93p6vvr4ueg4l38q7e8"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1raa77u23fknzduf32ntfgf0zjscmcjg4ugfwvs"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1l794vprkpja578g0fglzql68dn4etpgjry85cf"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1z0ngfqf95jpdg59ccdrq7ql8udt3t3m0rwygha"},{"name":"Netflix","symbol":"mNFLX","decimals":6,"total_supply":"0","contract_addr":"terra1yzvp4sdunfu84vhygqqr88yq3eydrfpdua838k"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra16q3zw87sj5l5dpm0acws8kvlezvehs7pxkw4yt"},{"name":"T-METAL","symbol":"METAL","total_supply":"1259","contract_addr":"terra17jexetpcgskw3ztjsrmzv0mnrv2nhywfjza4u9"},{"name":"Bonded Luna","symbol":"BLUNA","decimals":6,"total_supply":"1000000","contract_addr":"terra1336v4drlvx6w79fvykzaktch9r3gmcupvj5gu0"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1k59r2rgpnqaflxu2qa6q7xm22s8chxv23qwd2e"},{"name":"Rackspace Technology, Inc.","symbol":"mRXT","decimals":6,"total_supply":"592682","contract_addr":"terra14vmf4tzg23fxnt9q5wavlp4wtvzzap82hdq402"},{"name":"Coinbase Global, Inc.","symbol":"mCOIN","decimals":6,"total_supply":"744450436","contract_addr":"terra1qre9crlfnulcg0m68qqywqqstplgvrzywsg3am"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra1ghlarudtut6jpaav7jad45g7r5xl796ce672cr"},{"name":"MK Coin","symbol":"MKC","decimals":6,"total_supply":"1000000","contract_addr":"terra1mmd3lrs2qzacca22mfltsvwq0kh42p5j2uccdy"},{"name":"ProShares VIX","symbol":"mVIXY","decimals":6,"total_supply":"5011520116","contract_addr":"terra150ec7cwlsne4xh6h2z88hkrkgf37s8un577xmx"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"24634722946","contract_addr":"terra16vfxm98rxlc8erj4g0sj5932dvylgmdufnugk0"},{"name":"T-METAL","symbol":"METAL","total_supply":"1260","contract_addr":"terra18ah528064a7exp5e0axt2rr9l7ycfzfps9na85"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"938001262","contract_addr":"terra12saaecsqwxj04fn0jsv4jmdyp6gylptf5tksge"},{"name":"Apple","symbol":"mAAPL","decimals":6,"total_supply":"0","contract_addr":"terra10yngewgm4e7jh5trzlxvvudkygp4ls5aum9uz5"},{"name":"Larimar Therapeutics, Inc.","symbol":"mLRMR","decimals":6,"total_supply":"0","contract_addr":"terra1anw5z9u5l35vxhhqljuygmkupwmafcv0m86kum"},{"name":"Nebula Token","symbol":"NEB","decimals":6,"total_supply":"1010000000000","contract_addr":"terra10tuk3umkxnfzzavjgmcr837p34dmnluupugpw8"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra15gqpp2nfkcyufzstwhmf47uqsfywtugxk4gpqv"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1747mad58h0w4y589y3sk84r5efqdev9q4r02pc"},{"name":"Airbnb Inc.","symbol":"mABNB","decimals":6,"total_supply":"6237155890","contract_addr":"terra1avryzxnsn2denq7p2d7ukm6nkck9s0rz2llgnc"},{"name":"GameStop Corp","symbol":"mGME","decimals":6,"total_supply":"1896537420","contract_addr":"terra104tgj4gc3pp5s240a0mzqkhd3jzkn8v0u07hlf"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1ctwk3pju8q6h7ee4r45grn3enlx57ze5ve09s6"},{"name":"Kansas City Southern","symbol":"mKSU","decimals":6,"total_supply":"204999988","contract_addr":"terra1qhkjjlqq2lyf2evzserdaqx55nugksjqdpxvru"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra1rdqzee32lhf62g2va6755qvqqtzfxd8wl8k8h6"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra12387s42fcuyqfxtpdl02a0vaghtfuhn0kdjtla"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1x7sn4v7vqylx9yu8099gmd5khyan487dvmw74e"},{"name":"Tesla","symbol":"mTSLA","decimals":6,"total_supply":"0","contract_addr":"terra1ggsnhv6py7t653pgw9aqjazf53dqfws4hhqh8t"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra1k0xr8dk8zawttluyx7cqet2a72c7ghca23uj05"},{"name":"Alibaba Group Holdings Ltd ADR","symbol":"mBABA","decimals":6,"total_supply":"0","contract_addr":"terra1laddrrwxn5ltzfh7el69tymawml0leuehwch42"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1pehvgjqen57kgtv6xsuxe2ww6pcktsxp2h6yje"},{"name":"Twitter","symbol":"mTWTR","decimals":6,"total_supply":"0","contract_addr":"terra12cqtvugktnyhlg453y8lp97j3yrxdrdqv6lp9l"},{"name":"Invesco QQQ Trust","symbol":"mQQQ","decimals":6,"total_supply":"0","contract_addr":"terra1z25wdtwspdvzx7hgsp0jhr0qhwnwj20zsyu7h3"},{"name":"LoTerra","symbol":"LOTA","decimals":6,"total_supply":"7000000000000","contract_addr":"terra15zx3xekhcur8jckvn3dz59t65dh9wmu86yh30e"},{"name":"Amazon.com","symbol":"mAMZN","decimals":6,"total_supply":"0","contract_addr":"terra1cj05qcv9clvxsz4faydjzv6k77aj2p4cpzl9vg"},{"name":"FelixToken","symbol":"FXT","decimals":6,"total_supply":"100000000000000000","contract_addr":"terra1seyy7lg53eyjgm9p3zyscneytm4p3ada8fjhg3"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1ejfz5whfldj6k8qtr2ggmyuq5yshdqh2a4k8dq"},{"name":"Goat Token","symbol":"GOAT","decimals":6,"total_supply":"20000000","contract_addr":"terra1muhfdyv5kwkwc7cpycc7tczqg3v7dz77kkyhyr"},{"name":"iShares Silver Trust","symbol":"mSLV","decimals":6,"total_supply":"0","contract_addr":"terra17w8ukm8nrp3avzhjj7kwfqk2g8r2gx8vkp8evd"},{"name":"United States Oil Fund, LP","symbol":"mUSO","decimals":6,"total_supply":"0","contract_addr":"terra1xdtqc598nn9gc8wc43f9dz2sp3dwwlwvsqp2sc"},{"name":"T-METAL","symbol":"METAL","total_supply":"1257","contract_addr":"terra1j9vaxl2qpqpzvhna83ldak90fr9d7e6p5c9xl9"},{"name":"Test Token","symbol":"TTN","decimals":6,"total_supply":"1000000000000000","contract_addr":"terra10xz5p63unpsgmm7zeqd3wph896xpjagvcj93hs"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1774429992","contract_addr":"terra1gdglgpm84pdzuedc924wurhsqd0vs4nv4tpmh8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"22630826116","contract_addr":"terra1qxurxcgl30eu4ar34ltr5e9tqc2gjl4atspvy3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"116580824069","contract_addr":"terra1m9lf50qxajujllyacuwmy3c28kk6fjayezvn96"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1jpxa7xfd7tw0tvpmrwjndnwar9catw828uhs2f"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1tnzhg4tny3zj0qtw8qp448466c3aqen94e5ap6"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1em86mmur5tfysqpdq06dcep8vh8jfrld255rud"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1smcc94557d4zf9dlytxd9k4yx2ylhuxr9fjcgs"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18fdaw8452kc3w6lnqg5nmwexe0l5w2kse58tez"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1lku7tx4k3ej54ggjhmkad7fktftsczm2jemvnh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1wj8cm3h7fe369nl8j4ddukesfuy9l3hr4hjw22"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1u0sx20at9gj5596zrlymuu3e5fxy6ujdklqqlc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1hpv0pk8vme7w2c2h0fk984sp4rcd9u25eu9ydp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"100000000000","contract_addr":"terra1u3g737cx5tyuwpmf8gxnn4dymxlaq74rzxjg4u"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12zkcc39rpkzhsgr4d3t8emdpek0z9qvc905rpu"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1s9kjsuurw7eaca3yztuqngelpp0lc99mpcf470"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1gvjhp3rd4f7y9qe4jjurywezw3w98xfrg28vzy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"251475308468","contract_addr":"terra1ud750vcv39hd467sj2kk6s6nn8zf5xhgggf7uq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1uul30hh2705szk5ll2kfm9rvvp3fs5guyh5gsa"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"466732658","contract_addr":"terra1d8mk480l4sp3j095apcpqckrxyxqrsq6zapfzy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1lyg077vw362ptue8tgj4d0x4u8lrtf4tpvrdhe"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jeh6gyktqqg0temcg0ru6a95pr39npecnp4vn5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1x2x2j3h9xv35yc4h4n35j7lpjcxmrq45vjlqsl"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vw4mtwjym5fan8t7945pfwzh657ptl8clph5c7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1c4wze20c4wmxwdpgwy6v0vxwvelk98e9a2n0kj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1nmp4ujtk6ar0xe2pu6jg893ganzqnyzfsl0nud"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1qpuzkxx477vereptngkl4kqrkzl0v8srhx2jgh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"185482702","contract_addr":"terra1tv648ag99htdlqh82ct55hf00nq3f5mnrgxys5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14y53gud4n0jwzpcrq2ya43rq0cdwzdv56la37f"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1t9ls38d8uaeqhw98y396wuz0ucx0arhr5qx99k"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rt2g8ueyaxfmfn5fmye40jv2n63595z7qjluv0"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1wyn6tp45cy67yj68hlmpxmzvr9dndg8m34l6gw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cahu5a745vzyae65nglhne8sqzwvcyy300t26k"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cwvvjjvna6areuvx0fafcnpk0lqrteclhtv5he"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1hhynw27m5n9w4ff7yl3sc5l5mu2adg5ysq46mx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"181334296","contract_addr":"terra1hgfjtuspekfzjl6zx32u345mgtpf3g6za7twz0"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1900255177","contract_addr":"terra1lgxdj5wag4ug7le6arda5pd7z9xlpstgc2ue8t"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cjy6x5flsgdeu6600ur75se8a46lg2a0mrhfzx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1nt7ur7tdaahvynhradv3kggrf6c29txssdhfhz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1dnq7lwaela327ps6vk373e08m2ake9cpeme27z"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1gmjd79mt3pv8vdnz69769sk0tk4tla2hkxh7f4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"227621491714","contract_addr":"terra193c2xvuzswct8qtsg4e6qhe3hyt3l6fac9cy79"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1tuuyurzx5p9gvgz53eksgj8wjhgvz87xyct9lk"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xj4a7uhavktkv5rp20z0mc7hnneu4v2s6c5q2y"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14prwsdqhmpgcgt37hunmlwagjqspw3yadfamn9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1lt2d6e7saaaf5p3905u3kl4snwsr0j2qpkr9m7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1w0mxcvn7xjgpmr6nvhqlc8009p792k7cu8u04r"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15zq6q4mat3wkmfehearyhan2u920pwf27wp7vf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1yh39ehhz9a94kxqtkxc0kuy2a9atxhynmkpxyd"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1m63qlz6x7hce60u8rx75dgf86xvahdlxhd4erw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1pzvgpkpacrxxem6jdrfyf9m7ttkjk87askxk8s"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"108037700148","contract_addr":"terra1h52zc9qmndczgru9vp2cvuwfclyykl5yt3qjk8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rm9287fl7k37hlfvdv8kjd785838pe3vus7hpq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1r9nkkmml4dl53qr5k3gw7g3nevvyaqzafxl2fp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1h9zrywpukj2wvu5dfsm7tcxk8mwzzyrxenshsn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1tn5p4n2xh45nt9ym9hkq98vgy55ksg73sm544l"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vqlsgf3z5shrg3lc6479dsyvnrmg8s4zcc643c"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"604054027061","contract_addr":"terra1usrmk383nc6vjqq9sahkaca0p9k6cu0arvys43"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fcaeugent6xp3lzut4qrr2kfaer6808zkg78u5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1x0ehaemtdxzrgsxrp0hg3nkzas0yast500lunj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1w9a093cdmdxy05zmcfn9gm6t4n3ye5gtzza047"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10ek5fyuz6dguhlhxvm8ct2ff40k845v89mrdq7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ufk87mn73mdgc5ak2u0g5hja9enwsyxwda4ffl"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1syqy6pvg9ktsgrdslcqc2fuvsafwqgjjptttzt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1h6vzc7489dgtdmepw9qxg7hrvpzzgrtp7w4ypn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"204731029206","contract_addr":"terra16cn5cgwaktrzczda0c6ux0e2quudh4vn3t8jjm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"176031856922","contract_addr":"terra1rag9w5ch0jrdxjffr6napqz0zsrpm6uz2zezmj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra16x28ac2k9n8j8k94chs77gfzw7lcf9r8jh7vdq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1d72euqmmzkf7jlu9ja75nr7tus29ezcm45t86r"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18rzhzy4dtwwc4qydn9wpjlzjtwfppkj4llua9l"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"48","contract_addr":"terra138z52ev976ggsqt0hhsq3vps7nmtwzslzvtfaf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2146481277","contract_addr":"terra1txe366m8dj8jp75uwwa62nrytpm4vxvlz4hur2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"128240603618","contract_addr":"terra1f7azmktepw5rq35e2m6r6smtwl8wdrxp0dsvar"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"33357176701","contract_addr":"terra1kgvcrtupc8y4dgc9n08ud99ckdxp08j59zgccf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1pjqq53ygc65n5np9s77k3rcqfe030tck4lutqr"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1uzhy6t7jqah6hhqewp2s9203cfarsmfnzqtnmz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1f7y8m386ajxp8x76c3kd4a7whuxdkyzyyy99d6"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1gzsj6qkuz4v0dc636qn3e98azt0jn0cqqf37et"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"89813485","contract_addr":"terra10eawrjezhp4y56p28fjr00zu5vjj2ezah8kqvt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1w3dnarfxvcew7mx8j0rszdx85wh49km50vdsgq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra105mjjngs4zjscc5ngx3zmeg3lpr6advujfn4xk"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"497","contract_addr":"terra1ulwkt6lgv5yevp85vkdgryse9049xzr902f8dm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jnk8sgmsh6eq3a74g6sk8y5c4kp2ddx4rf5zsn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1zxdjdg8xx7rkfw2nf37lnlg3upu9dv45w9067g"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1grn60h79r360wla2cuc95m9prd33lhexp2c390"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"10000000","contract_addr":"terra1r6lyg7j38wxyv0w9zhj8jyqpm0vz3wrrze5020"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2394175","contract_addr":"terra16qpyqzmudklza73red8vx87g5prafz0v226ck3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1y4yxd3navpw56rr4g2j8ev8cafllkpdjr6y5jh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12s6df7vawqznpns2kem5yw4ku8jk78r5dgdcyf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1aceyfta7gwzm90zdjya7e8j8v3n3xfmkncfcy5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14wma8c75gk5xj53t3dqvs7hn2ac8v4v55vxsdn"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1nvekhfc4nsjxlg9pscu9cqucchdzteny24p63v"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14gkpyxht4ln9vlgzy2akxmfrlp97fdps5w9gu4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10ry5e8pkgh9zzl4fnyx2fsts6fn2h95kp9chwt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ct8lx247n7wsl9a2ny66pkmz2ze0ejnf5prnu9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"43158696436","contract_addr":"terra1e0njrqcsehxpt9due62x9zsxl7h9htl0xqdujv"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1n0fqzdfsqvd6g98hf4aq9n7laq5rcq3vv6kt5p"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"100000983767","contract_addr":"terra1uhf9u4a6vtkvnwn4cw6hmzaxm5zzzn6ukmjq2g"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1haq90apd9q8hf5wjcyy02sc6vz9sg0c4wgm85j"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra195hw0l5as7mnvuxrnw04q40tvtrcljuzfnqww3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"69820522","contract_addr":"terra1k5rz6hh83zdufxgca22r0tygtdp8kx07g3yqs7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"747594477","contract_addr":"terra1m6gdmafv8ece7ekq5m90l9tz59u2hkp7umy5cw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"126490","contract_addr":"terra1qw706xj3dxqg8dc4sqyfyxy5vtlaz727mwcv9c"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"400348","contract_addr":"terra1yuht5ghy0vfcqewyhttmfn4n5am7k05akzetu5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vgj59typ39hvgewy824g3uf42fjeegvd4fcsqy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2279483320","contract_addr":"terra1srf30cs8ax73y59gm64lkztnx0zexl8fpv3kx2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15rdu8m5x9d8jjxheg492h0yqshz3evp7a49ey8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12afyjv3xpw5tx8mm90fsrm0nelg8vtpgahxeht"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"10000","contract_addr":"terra1xls9qp0dy0hej5lmpr3rrdfnys52a3f9nagxup"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1yc3s4cgpw4ygxc4x4e76art9ygv7yldlqpsgfw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"94867","contract_addr":"terra1r6vqveujzcuajx9xn2zwnqdg0q66e9c0fqjtw6"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"10004543739","contract_addr":"terra1tj4pavqjqjfm0wh73sh7yy9m4uq3m2cpmgva6n"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fpkuyvd87ysaq6j748e9h7tspfpuhrkdjl979v"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12s7j52ufxe4wcgp3e6et0nfu6f97n7ljevhkgx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1qqmq3nzm22ku8zw960670r0xsnx5x003nwdej4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1klneugg75zkvq40j2t9s9xcgw2z33tels680xv"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"2671043301","contract_addr":"terra1k8atz96j9cccv6hspwly7qwztx0mls98se4ku9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rq7h2hu3wl7sgpwq2wjsesst3sku6xcaj2env8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1hl4va89ps0qhyakr7jc9cwljq36rg0kpxfusjp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fz3xuz4ujzccthc6t4qy2rwrglsyextc37gh2x"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jz08nhqf3aju4rs8cyshfpzfj704sa3l0cnhvz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vnscj5g5flx6lnnhzzh6lvdphw0d47vs4uhrrk"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15dvruqq8z28urulgx5hwvzqp76c72p2s7zeq0u"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1edfdt7r8fht0al9s99yama7z3yp53k50qeccpx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1318371718","contract_addr":"terra1gt7gh3rgtjcd9mptfayzjlsydj4zpgmtpsnd6r"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vxzzk6k9k35zp6d6u4p2yql3gghsnlcegydar2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"4388165803","contract_addr":"terra1kkpe6has6g55nhyqp6vkw0wk8z3u3nq6fz6znc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1q7nagslgzw5euv92gcf8sy7ysgh434x4segqtj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1nnup53aq7efjcf7af5x6cla9aqrcvtqwna0a6z"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"426719389171","contract_addr":"terra1zrryfhlrpg49quz37u90ck6f396l4xdjs5s08j"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra15dsaa5lct74caedrddlcv0xhyf53963gcpctr3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cv4xjgw87hs00jurgjvf9m3eze2se8x2set0kl"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1e56epgvcug2l5ztu48vkv6e28cd3mhhdpqwkmk"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rguh8jh2f5pgzvc4eg58f59tu7j42v4sr5vfr9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10drp42048sfm27zyllz2297anx8wsd0vkf32c2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1nm9l4gvyz249padk2nm4xpenry466m30mdq0cq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1a45yucku9sx8785002l28rxwe2zp5fuweu0j5s"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1w8tmwpjufmety73hvf69uw3v6t4r7qjytyzu38"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rcjlewd2aj6750n2t3s7dxuu7wmhzsnvsth7yc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fjcw2kqglp7rl6cv34hrj806tjx9x3ufpqsvl8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jh207gkf2cpkfwgyztvqzgagj5rpsw4df8zgt7"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1kf3v4pwrcs332qmc4j09pv6e7fs5ldrjxazce2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"42995088679","contract_addr":"terra1zf7whnwae5suut72j8tnrztn3gp0ly3mvd6a9k"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1gcrt88kskwlq3mrdm8d3x6nemedtcazdn66v4s"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"3182758310","contract_addr":"terra1xwk2x2pyrhlshjgnlv3ql5q8r8r8vyrdf6u2mj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1p5a3nd8jakg45xtv3vn82wf7nunhauted4hehv"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1vtswnef0hgyjw73nc0zk07js9h5e9mudkj2qad"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000000000","contract_addr":"terra1fjtydpc8hsgy2er36h4st6aur6g625e02sltqc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"497","contract_addr":"terra1sudtnq8ngps45e5t7e3hgreexdrxlt2s8smr3d"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1kz6uqax5dkm75a7n4jcxkwgy60qvshhh7jfdny"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1s6qvvl4c09czvythawumn2sz8vawyg7atr0jk2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra17u7dh6wyzeyjnkunw5qf9693ahcvuhavf3dhr9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cpr9m0gyqckww5zhuwzjnxh7fq0r904t40evh2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12qe96zmpzyq6gwfqxfc02mfg0nwsnp9n2kpygy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"707106781","contract_addr":"terra1s0fkkjuqc7rr84p0t0nn6g0ahmv0wcvcaky66p"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1t7munychjx6jhqwucfg6u7j6q9qpr0wk8dxtwc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15pxnu22ks4khkhcrx29ens6kh3n3qcqqvhzrt8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xzfwzckll455r6jdjdcrj34smyam74qwyta6th"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10pc50h2923jg6mp94rq9x9enpnzqsr6xyu7v7f"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1hmwdk354swajl95g0l954f5lc6k7esdvwjsw3a"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"182491878","contract_addr":"terra1adfne9dyfav3rml2qpkw86nhy57qpjuzz4lpn2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"116976959656","contract_addr":"terra1utf7qw0uce42vqsh255hxgd3pvuzfvp6jcayk5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1p6ys86xyj4xxyv4d4d9lghyy2rd8j0u2jnsq4d"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra13a5vak807cn9m6erp7fcz3jflc785tg36yz9c6"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15a7dp97phtqw89nxuvmdlsglf7avphnz8a0sg4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1pef9fz8lkqajzuwp6ff6t33s86ndpkm3728cgc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"115220778661","contract_addr":"terra1px2ya3e07aprfgc76e57r3nuvy3czssrvcxg9t"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"6889892555","contract_addr":"terra1fm4a958rxp0jacpssq4h2pvlefevnnyr36jgh9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra15kuu6guy8kuqrujxkqjuz7q8qt9p2j5wy8n3km"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10nzc4tm5ndryrnxpjwv4j2w32f43vr28jqexgw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"68636218","contract_addr":"terra1wp4tdte4vw49p6nf847dezl5mm23ds0exj23ey"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jn7tdgvec2ajs63lg9cmc3dd04n2sv59mwvflu"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"4139936038","contract_addr":"terra1l8c87av89cczj20mguxy0hmp6k6hesr0yjthkm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1l5wznvgvzetj50w02v065rnq08srxtr8zqta7l"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1a22k49xtmn7l3f2zengxjm524vp6jr4vtfcv0d"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra10gmkfmnn9nrc9k3wjqltajflpx5ngnv98es2dh"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1muwctenfn3eeza5v23wc4c7phqxh5xlmu0u0as"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1qcjwkk4dmkdefjnw83tu9u4t3gmeryt7j7249r"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1h8cqwj6wgzktvnv39k23wmura4v9vwtv8mn7cp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1tjtp5tumqx5ndexf23ceedvm5v57rdr9ya83wu"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1zzf9qje6vhs8aky9m9yjq69j79fddngk2ku74c"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"98281625","contract_addr":"terra1u5mzjkd3t3md6yart8s0wcnfqptxtn2rc9euzq"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1u2xfhusmzttdem3vehv3vys3ttkvn7u7sdfux5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1sppy2rc4yu4uur6m62r5pngq89hgf8hv2kyphs"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1kkf9t79k8e4m6edhz8ztex68np7f4us20jwg3v"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1z57k70qf86yswz348ve7u9wk9sa9cudr6977xz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"1000","contract_addr":"terra1kxzds5fdhnnzp2v78y5fwhgl03fqj2cpucxlmz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra13xxu2fhc0gtpc0e4dg376gq5n45nft55aztxwf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1g8lm0ydthqp88lcs28wpdq49hlx42yy357meql"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xd6r7zna9s5x2449ujuhd9f8uepwqchf3m2n97"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1c8m8jqyv7newzqtcerrv80hl8flflhyndd9dy8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cckr6twmgaj0y0pnf8x845m5jdudckr0qtpkrd"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fnqw7xff7m6te8aw9lzpz58f55wt7vrz3j2504"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14ntkry6r8ewzmyscfr8ppejem3ua8xt4rmd8xz"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1e5wd5n0wquu8cj5lav2ue2yq5zpuax3kj74js9"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra150z80ekm6sj3w7wfa039h4pd7f29g3djs6yjne"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"719937192","contract_addr":"terra186m890y8hzhyhp8emgsy2a8jqvsgluznc688xf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra16s76vcer3hd88nh2z757wjlmlttc7kysy2dpsf"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ngls4wmcdnjh8ztqc9m040x9z9m9ckxcm4r55s"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cajt6uxet8t72rnftt0p34h505y46ela7dzhd8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xer9xcvca6vxuj6ccnesp9jjeh3rr4tp7a4gm3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra14z5akfspypxxadmtn6hnh32a4xv2wqjh6xnwf5"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra174kqwwucmt0gvzkk56d03689vs0gnvatdtfvds"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xqfkuffmfmgvpwqmrmueejjsk55xdfjep8w86q"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"22656032","contract_addr":"terra1djspjy6c35tx83uqxvgujf2rtkevywpt049wfw"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1z045gzcmsgl7w3v6v4fk6eepzfjq9mk8vxvk54"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1aed920faqfxc6uau40zzqnf6hwf6nntyj7la7x"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"173225641048","contract_addr":"terra1vth958fsn8zawllaqcdzswksjkv3dz2sqqmcu4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1cuhnk59cd6cf5v33zwn4qmfl6gk6t3hrpwczrk"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1gwplzfstdyvj7nvma38zgwaq4k9p3mg6l73uyp"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1mzxe0q9lsz8amnxwv08x46s2hwv90aqsq4dnpm"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1eqmtmvu69dxpkturv4enhe32qeh8yuv4nnslsd"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1fhrusf8jq5xjv67cl0daxlpve4lm253t45ex2v"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18eg7frnkt38ecumj76ym7k55e7qp38cf2um2dt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18x4f797r0gzcj37ef2sqqnte5cuqg7yl45zmqt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1tyu8ghnjv9pv9scj24kckmvd2rummttjlpagv3"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1uxqwtchvf24ttgh3t80azlg9gx2ajuk77pglnj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1g7fsw8c7f53jqffqdx9g56utalhcnvusc95r6k"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1xv5tva4x9kg9pl2ws5rlfr532zqe3jha9q4pgu"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"150454123653","contract_addr":"terra10cugucjwn4hdtvavl0n2sh2ke64nx93luhj49k"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"5380193801","contract_addr":"terra1d7xlu53sx9anwdqvxeya0tmhr7xzepd9agyvft"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra136vd5a23hhywz872n7t8f8egrq8kkwrpawdsf8"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"81805598","contract_addr":"terra1gvy4nl65dlgvpamrvf5ly4mdlkjz4u0fh0ve7g"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1em8rm43decqdtp9ckk2ufcvp3wuvp4k3h7jd3m"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ps4628n4m2ur2me37a00mxyfv2qv4cndz6lzsc"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra18lr8suw20k43wrcp82ahzjxad0gsuzxd000v02"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra156h8gnadm7uanp03qes8wfvd9kfpxp7z2n0mu2"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"674122689805","contract_addr":"terra1vg0qyq92ky9z9dp0j9fv5rmr2s80sg605dah6f"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1aq03n3lak7728e3nu0uwdaf2cft7enmu66scxj"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra12tj7l2w7gft3elev6e4fcz0satymx9xty4wpce"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1y933pfdtyqzgsv39d70dyp0udcftlz4fuz0lw4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1dsh250fmcp7e3022wvzvyykynna4epgqad0hdt"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1jwszz9nfywrksgsvu60tujsckswdyyc0qv8pgg"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra19rfgyqtnq7wr4hhfk37zkz0eaplc6ld4f694cx"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1da03xjnqu7pdt847hwcqav6gwymmm5x5l6prw4"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra184nwn9hugva4x2j72w35mr5kmnfrmgzff5fvwy"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1rjjzr8csdp0vxq2htrl8xvfsc393h5v43kt3la"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1ufqugh6t3aupu5d5569j53dp86fn2rywd9ej5n"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"0","contract_addr":"terra1wek9arpnwz5j3j4wmreae3fhyupwl25yvu793t"},{"name":"terraswap liquidity token","symbol":"uLP","decimals":6,"total_supply":"63371414","contract_addr":"terra1xhsmcr9rcmxxp02d9hxq5r752ndr9g3m7y8ezw"}] \ No newline at end of file diff --git a/src/forms/Asset.module.scss b/src/forms/Asset.module.scss deleted file mode 100644 index c9c0a3de..00000000 --- a/src/forms/Asset.module.scss +++ /dev/null @@ -1,35 +0,0 @@ -@import "src/styles/mixins.module"; -@import "src/styles/variables.module"; - -$symbol: 14px; -$name: 12px; - -.asset { - @include flex(space-between); - // Because only one line of data can exist, fix the height. - height: (($symbol + $name) * $line-height); -} - -.header { - text-align: left; -} - -.symbol { - font-size: $symbol; - font-weight: 500; -} - -.name { - color: $slate; - font-size: $name; - font-weight: normal; -} - -.footer { - text-align: right; -} - -.balance { - color: $blue; - font-size: 12px; -} diff --git a/src/forms/Asset.tsx b/src/forms/Asset.tsx deleted file mode 100644 index f161ac57..00000000 --- a/src/forms/Asset.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from "react" -import { UST } from "constants/constants" -import { gt } from "libs/math" -import { format, lookupSymbol } from "libs/parse" -import styles from "./Asset.module.scss" - -interface Props extends AssetItem { - formatTokenName?: (symbol: string) => string -} - -const Asset = ({ symbol, name, price, balance, formatTokenName }: Props) => ( -
-
-

- {formatTokenName?.(symbol) ?? lookupSymbol(symbol)} -

- - {name !== UST &&

{name}

} -
- -
- {price && gt(price, 0) && name !== UST && ( -

- {format(price)} {UST} -

- )} - - {balance && gt(balance, 0) && ( -

- Balance: {format(balance, symbol)} -

- )} -
-
-) - -export default Asset diff --git a/src/forms/Assets.module.scss b/src/forms/Assets.module.scss deleted file mode 100644 index e969c826..00000000 --- a/src/forms/Assets.module.scss +++ /dev/null @@ -1,57 +0,0 @@ -@import "src/styles/mixins.module"; -@import "src/styles/variables.module"; - -.component { - @include flex; - flex-direction: column; - align-items: stretch; - height: 300px; -} - -/* search */ -.search { - @include flex(flex-start, stretch); - flex: none; - margin-bottom: 5px; - - background: fade-out($bg, 0.5); - border-radius: 5px; - height: 40px; - - label { - @include flex; - } - - i { - margin: 0 15px; - } - - input { - flex: 1; - } -} - -/* feedback */ -.feedback { - text-align: center; -} - -/* assets */ -.list { - flex: 1; - margin: 0 -20px; - overflow-y: scroll; -} - -.button { - padding: 10px 30px; - width: 100%; - - &:not(.disabled):hover { - background: fade-out(white, 0.95); - } - - &.disabled { - opacity: 0.3; - } -} diff --git a/src/forms/Assets.tsx b/src/forms/Assets.tsx deleted file mode 100644 index d9f5bf59..00000000 --- a/src/forms/Assets.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useState } from "react" -import classNames from "classnames/bind" -import { UST, UUSD } from "constants/constants" -import { gt } from "libs/math" -import { insertIf } from "libs/utils" -import { useContract, useCombineKeys } from "hooks" -import Icon from "components/Icon" -import { Config } from "./useSelectAsset" -import Asset from "./Asset" -import styles from "./Assets.module.scss" -import { useContractsAddress } from "hooks/useContractsAddress" - -const cx = classNames.bind(styles) - -interface Props extends Config { - selected?: string - onSelect: (asset: string) => void -} - -const Assets = ({ selected, onSelect, ...props }: Props) => { - const { priceKey, balanceKey } = props - const { useUST, skip, formatTokenName } = props - - const { listed } = useContractsAddress() - const { uusd, find } = useContract() - const { loading } = useCombineKeys([priceKey, balanceKey]) - - /* search */ - const [value, setValue] = useState("") - - /* list */ - const list: AssetItem[] = [ - ...insertIf(useUST, { - symbol: UUSD, - name: UST, - price: "1", - balance: uusd, - }), - ...listed - .filter(({ symbol }) => !skip?.includes(symbol)) - .map(({ symbol, name, token }) => ({ - symbol, - name, - price: priceKey && find(priceKey, token), - balance: balanceKey && find(balanceKey, token), - })), - ] - - return ( -
-
- - - setValue(e.target.value)} - autoComplete="off" - autoFocus - /> -
- -
    - {list - .filter(({ symbol, name }) => - // search result - [symbol, name].some((text) => - text.toLowerCase().includes(value.toLowerCase()) - ) - ) - .sort(({ symbol: a }, { symbol: b }) => { - const hasA = balanceKey && gt(find(balanceKey, a), 0) ? 1 : 0 - const hasB = balanceKey && gt(find(balanceKey, b), 0) ? 1 : 0 - return hasB - hasA - }) - .map((item) => { - const { symbol, price } = item - const isSelected = symbol === selected - - return ( -
  • - -
  • - ) - })} -
-
- ) -} - -export default Assets diff --git a/src/forms/ConfirmDetails.tsx b/src/forms/ConfirmDetails.tsx index ee436312..42e99854 100644 --- a/src/forms/ConfirmDetails.tsx +++ b/src/forms/ConfirmDetails.tsx @@ -1,4 +1,3 @@ -import React from "react" import classNames from "classnames/bind" import styles from "./ConfirmDetails.module.scss" diff --git a/src/forms/Result.tsx b/src/forms/Result.tsx index 76087df3..d5c3e4ec 100644 --- a/src/forms/Result.tsx +++ b/src/forms/Result.tsx @@ -28,7 +28,6 @@ import { createLogMatcherForActions, getTxCanonicalMsgs, } from "@terra-money/log-finder-ruleset" -import { SwapTxInfo as ISwapTxInfo } from "types/swapTx" import { TxInfo } from "@terra-money/terra.js" import { TxDescription } from "@terra-money/react-base-components" import { useLCDClient } from "@terra-money/wallet-provider" @@ -51,6 +50,7 @@ enum STATUS { SUCCESS = "success", LOADING = "loading", FAILURE = "failure", + TIMEOUT = "timeout", } const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { @@ -60,7 +60,7 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { const txHash = response?.result?.txhash ?? "" const raw_log = response?.result?.raw_log ?? "" /* polling */ - const [txInfo, setTxInfo] = useState() + const [txInfo, setTxInfo] = useState() const matchedMsg = useMemo(() => { if (!txInfo || !network?.name) { @@ -72,33 +72,46 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { }, [network, txInfo]) const [status, setStatus] = useState(STATUS.LOADING) - const { fcd } = useNetwork() + const { lcd } = useNetwork() const retryCount = useRef(0) useEffect(() => { + let isDestroyed = false const load = async () => { + if (isDestroyed) { + return + } + if (retryCount.current >= MAX_TX_POLLING_RETRY) { + setStatus(STATUS.TIMEOUT) + return + } if (!txHash) { setStatus(STATUS.FAILURE) return } try { - const { data: res } = await axios.get(`${fcd}/txs/${txHash}`) - if (res?.code) { - setTxInfo(res) + const { data: res } = await axios.get(`${lcd}/cosmos/tx/v1beta1/txs/${txHash}`, { + cache: { ignoreCache: true }, + }) + + if (isDestroyed) { + return + } + + if (res?.tx_response.code) { + setTxInfo(res.tx_response) setStatus(STATUS.FAILURE) return } - if (res?.txhash) { - setTxInfo(res) + + if (res?.tx_response.txhash) { + setTxInfo(res.tx_response) setStatus(STATUS.SUCCESS) - } - } catch (error) { - if (retryCount.current >= MAX_TX_POLLING_RETRY) { - setStatus(STATUS.FAILURE) - retryCount.current = 0 return } + throw new Error("Unknown") + } catch (error) { retryCount.current += 1 setTimeout(() => { load() @@ -106,6 +119,10 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { } } load() + + return () => { + isDestroyed = true + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -114,6 +131,7 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { [STATUS.SUCCESS]: "check_circle_outline", [STATUS.LOADING]: "", [STATUS.FAILURE]: "highlight_off", + [STATUS.TIMEOUT]: "highlight_off", }[status] const icon = name ? ( @@ -130,6 +148,9 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { [STATUS.FAILURE]: ( {MESSAGE.Result.FAILURE} ), + [STATUS.TIMEOUT]: ( + {MESSAGE.Result.FAILURE} + ), }[status] const message = @@ -188,6 +209,15 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => {

{txInfo?.raw_log || message}

), + [STATUS.TIMEOUT]: ( + <> + {txInfo && } +

{MESSAGE.Result.TIMEOUT}

+

+ {txHash} +

+ + ), }[status] const button = { @@ -202,6 +232,11 @@ const Result = ({ response, error, onFailure, parserKey }: ResultProps) => { {MESSAGE.Result.Button.FAILURE} ), + [STATUS.TIMEOUT]: ( + + ), }[status] return ( diff --git a/src/forms/SelectAsset.module.scss b/src/forms/SelectAsset.module.scss deleted file mode 100644 index 80d6b527..00000000 --- a/src/forms/SelectAsset.module.scss +++ /dev/null @@ -1,10 +0,0 @@ -@import "src/styles/mixins.module"; - -.button { - @include flex; - @include link(white); - - i { - margin-left: 5px; - } -} diff --git a/src/forms/SelectAsset.tsx b/src/forms/SelectAsset.tsx deleted file mode 100644 index bfbc43ec..00000000 --- a/src/forms/SelectAsset.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { FC, PropsWithChildren } from "react" -import MESSAGE from "../lang/MESSAGE.json" -import { lookupSymbol } from "../libs/parse" -import Icon from "../components/Icon" -import { Config } from "./useSelectAsset" -import styles from "./SelectAsset.module.scss" - -interface Props extends Config { - isOpen: boolean - asset?: string - onClick: () => void -} - -const SelectAsset: FC> = ({ - isOpen, - asset, - onClick, - ...props -}) => { - const { formatTokenName } = props - return ( - - ) -} - -export default SelectAsset diff --git a/src/forms/SwapConfirm.tsx b/src/forms/SwapConfirm.tsx index d443a978..12e0c42e 100644 --- a/src/forms/SwapConfirm.tsx +++ b/src/forms/SwapConfirm.tsx @@ -1,4 +1,3 @@ -import React from "react" import styles from "./SwapConfirm.module.scss" const SwapConfirm = ({ list }: { list: Content[] }) => ( diff --git a/src/forms/SwapForm.tsx b/src/forms/SwapForm.tsx index 8598822b..8322c39d 100644 --- a/src/forms/SwapForm.tsx +++ b/src/forms/SwapForm.tsx @@ -1,36 +1,39 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { useCallback, useEffect, useMemo, useRef, useState } from "react" import styled from "styled-components" import Container from "components/Container" -import { SubmitHandler, useForm, WatchObserver } from "react-hook-form" +import { useForm, WatchObserver } from "react-hook-form" import Result from "./Result" import TabView from "components/TabView" import { useSearchParams } from "react-router-dom" -import { UST, DEFAULT_MAX_SPREAD, ULUNA } from "constants/constants" -import { useNetwork, useContract, useAddress, useConnectModal } from "hooks" +import { DEFAULT_MAX_SPREAD, LUNA, ULUNA } from "constants/constants" +import { useAddress, useConnectModal } from "hooks" import { lookup, decimal, toAmount } from "libs/parse" import calc from "helpers/calc" -import { PriceKey, BalanceKey, AssetInfoKey } from "hooks/contractKeys" +import { PriceKey, BalanceKey } from "hooks/contractKeys" import Count from "components/Count" import { validate as v, placeholder, step, renderBalance, - calcTax, + toBase64, } from "./formHelpers" import useSwapSelectToken from "./useSwapSelectToken" import SwapFormGroup from "./SwapFormGroup" import usePairs, { InitLP, useLpTokenInfos, useTokenInfos } from "rest/usePairs" import useBalance from "rest/useBalance" -import { minus, gte, times, ceil, div } from "libs/math" +import { minus, gte, div, lt } from "libs/math" import { TooltipIcon } from "components/Tooltip" import Tooltip from "lang/Tooltip.json" import useGasPrice from "rest/useGasPrice" -import { hasTaxToken } from "helpers/token" -import { Coins, CreateTxOptions } from "@terra-money/terra.js" +import { + Coins, + CreateTxOptions, + MsgExecuteContract, +} from "@terra-money/terra.js" import { Type } from "pages/Swap" import usePool from "rest/usePool" -import { insertIf } from "libs/utils" +import { insertIf, isNativeToken } from "libs/utils" import { percent } from "libs/num" import SvgArrow from "images/arrow.svg" import SvgPlus from "images/plus.svg" @@ -38,22 +41,21 @@ import Button from "components/Button" import MESSAGE from "lang/MESSAGE.json" import SwapConfirm from "./SwapConfirm" import useAPI from "rest/useAPI" -import { TxResult, useWallet } from "@terra-money/wallet-provider" +import { TxResult, useLCDClient, useWallet } from "@terra-money/wallet-provider" import iconSettings from "images/icon-settings.svg" import iconReload from "images/icon-reload.svg" import { useModal } from "components/Modal" import Settings, { SettingValues } from "components/Settings" import useLocalStorage from "libs/useLocalStorage" import useAutoRouter from "rest/useAutoRouter" -import { useLCDClient } from "layouts/WalletConnectProvider" -import { useContractsAddress } from "hooks/useContractsAddress" import WarningModal from "components/Warning" import Disclaimer from "components/DisclaimerAgreement" +import useFee, { calculateFee } from "hooks/useFee" +import useFormData from "hooks/forms/useFormData" enum Key { value1 = "value1", value2 = "value2", - feeValue = "feeValue", feeSymbol = "feeSymbol", load = "load", symbol1 = "symbol1", @@ -62,13 +64,26 @@ enum Key { max2 = "max2", maxFee = "maxFee", gasPrice = "gasPrice", - taxCap = "taxCap", - taxRate = "taxRate", poolLoading = "poolLoading", } +type FormData = Record + +const defaultFormValues = { + [Key.value1]: "", + [Key.value2]: "", + [Key.feeSymbol]: LUNA, + [Key.load]: "", + [Key.symbol1]: "", + [Key.symbol2]: "", + [Key.max1]: "", + [Key.max2]: "", + [Key.maxFee]: "", + [Key.gasPrice]: "", + [Key.poolLoading]: "", +} + const priceKey = PriceKey.PAIR -const infoKey = AssetInfoKey.COMMISSION const Wrapper = styled.div` width: 100%; @@ -81,6 +96,69 @@ const Warning = { FontWeight: "bold", } +const getMsgs = ( + _msg: any, + { + amount, + token, + minimumReceived, + beliefPrice, + }: { + amount?: string | number + token?: string + minimumReceived?: string | number + beliefPrice?: string | number + } +) => { + const msg = MsgExecuteContract.fromData( + Array.isArray(_msg) ? { ..._msg[0] } : { ..._msg }, + true + ) as any + + if (msg?.execute_msg?.swap) { + msg.execute_msg.swap.belief_price = `${beliefPrice}` + } + if (msg?.execute_msg?.send?.msg?.swap) { + msg.execute_msg.send.msg.swap.belief_price = `${beliefPrice}` + } + if ( + msg?.execute_msg?.send?.msg?.execute_swap_operations && + typeof msg?.execute_msg?.send?.msg?.execute_swap_operations === "object" + ) { + msg.execute_msg.send.msg.execute_swap_operations.minimum_receive = parseInt( + `${minimumReceived}`, + 10 + ).toString() + if (isNativeToken(token || "")) { + msg.coins = Coins.fromString(toAmount(`${amount}`) + token) + } + + const newMessage = toBase64(`${JSON.stringify(msg.execute_msg.send.msg)}`) + msg.execute_msg.send.msg = newMessage + } else if ( + msg?.execute_msg?.send?.msg && + typeof msg?.execute_msg?.send?.msg === "object" + ) { + const newMessage = toBase64(`${JSON.stringify(msg.execute_msg.send.msg)}`) + msg.execute_msg.send.msg = newMessage + } + if (msg?.execute_msg?.execute_swap_operations) { + msg.execute_msg.execute_swap_operations.minimum_receive = parseInt( + `${minimumReceived}`, + 10 + ).toString() + msg.execute_msg.execute_swap_operations.offer_amount = toAmount( + `${amount}`, + token + ) + + if (isNativeToken(token || "")) { + msg.coins = Coins.fromString(toAmount(`${amount}`) + token) + } + } + return [msg] +} + const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { const connectModal = useConnectModal() const [isWarningModalConfirmed, setIsWarningModalConfirmed] = useState(false) @@ -92,14 +170,11 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { const tokenInfos = useTokenInfos() const lpTokenInfos = useLpTokenInfos() + const terra = useLCDClient() - const { getSymbol, isNativeToken } = useContractsAddress() - const { loadTaxInfo, loadTaxRate, generateContractMessages } = useAPI() - const { fee } = useNetwork() - const { find } = useContract() + const { generateContractMessages } = useAPI() const walletAddress = useAddress() const { post: terraExtensionPost } = useWallet() - const { terra } = useLCDClient() const settingsModal = useModal() const [slippageSettings, setSlippageSettings] = useLocalStorage("slippage", { @@ -124,21 +199,8 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { [Type.WITHDRAW]: BalanceKey.LPSTAKABLE, }[type] - const form = useForm({ - defaultValues: { - [Key.value1]: "", - [Key.value2]: "", - [Key.feeValue]: "", - [Key.feeSymbol]: UST, - [Key.load]: "", - [Key.symbol1]: "", - [Key.symbol2]: "", - [Key.max1]: "", - [Key.max2]: "", - [Key.maxFee]: "", - [Key.gasPrice]: "", - [Key.poolLoading]: "", - }, + const form = useForm({ + defaultValues: defaultFormValues, mode: "all", reValidateMode: "onChange", }) @@ -152,7 +214,7 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { resetField, } = form const [isReversed, setIsReversed] = useState(false) - const formData = watch() + const formData = useFormData(watch, defaultFormValues) useEffect(() => { if (!from && !to) { @@ -204,6 +266,10 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { return tokenInfos.get(to) }, [to, tokenInfos]) + const feeTokenInfo = useMemo(() => { + return tokenInfos.get(formData[Key.feeSymbol]) + }, [formData, tokenInfos]) + const pairSwitchable = useMemo(() => from !== "" && to !== "", [from, to]) const { balance: balance1 } = useBalance(from, formData[Key.symbol1]) @@ -281,20 +347,19 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { if (isPairsLoading) { return {} } - const info1 = - type === Type.WITHDRAW ? lpTokenInfos.get(from)?.[0] : tokenInfo1 - const info2 = - type === Type.WITHDRAW ? lpTokenInfos.get(from)?.[1] : tokenInfo2 - const selected = pairs.find((item) => { + const lpTokenInfo = lpTokenInfos.get(from) + + const info1 = type === Type.WITHDRAW ? lpTokenInfo?.[0] : tokenInfo1 + const info2 = type === Type.WITHDRAW ? lpTokenInfo?.[1] : tokenInfo2 + const selectedPairs = pairs.find((item) => { return ( item.pair.find((s) => s.contract_addr === info1?.contract_addr) && item.pair.find((s) => s.contract_addr === info2?.contract_addr) ) }) - const contract = selected?.contract || "" - const lpContract = selected?.liquidity_token || "" - const lpTokenInfo = lpTokenInfos.get(lpContract) + const contract = selectedPairs?.contract || "" + const lpContract = selectedPairs?.liquidity_token || "" return { pairAddress: contract, @@ -311,6 +376,7 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { to: to, amount: formData[Key.value1], type: formState.isSubmitted ? undefined : type, + slippageTolerance, }) const { result: poolResult, poolLoading } = usePool( @@ -321,8 +387,6 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { balance1 ) - const [tax, setTax] = useState(new Coins()) - const spread = useMemo(() => { return tokenInfo2 && !isAutoRouterLoading && poolResult?.estimated ? div( @@ -350,6 +414,123 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { } }, [isWarningModalConfirmed, spread, warningModal]) + const { gasPrice } = useGasPrice(formData[Key.feeSymbol]) + + const [createTxOptions, setCreateTxOptions] = useState< + CreateTxOptions | undefined + >(undefined) + + const generateCreateTxOptions = useCallback( + async ( + { value1, value2 }: { value1: string; value2: string }, + additionalOptions: Partial = {} + ) => { + try { + let msgs: any = {} + if (type === Type.SWAP) { + if ( + !profitableQuery?.msg || + Number.isNaN(Number(value1)) || + Number.isNaN(Number(value2)) + ) { + return + } + msgs = getMsgs(profitableQuery?.msg, { + amount: `${value1}`, + minimumReceived: profitableQuery + ? calc.minimumReceived({ + expectedAmount: `${profitableQuery?.simulatedAmount}`, + max_spread: String(slippageTolerance), + commission: "0", + decimals: tokenInfo1?.decimals, + }) + : "0", + token: from, + beliefPrice: `${decimal(div(value1, value2), 18)}`, + }) + } else { + msgs = await generateContractMessages( + { + [Type.PROVIDE]: { + type: Type.PROVIDE, + sender: `${walletAddress}`, + fromAmount: `${value1}`, + toAmount: `${value2}`, + from: `${from}`, + to: `${to}`, + slippage: slippageTolerance, + }, + [Type.WITHDRAW]: { + type: Type.WITHDRAW, + sender: `${walletAddress}`, + amount: `${value1}`, + lpAddr: `${lpContract}`, + }, + }[type] as any + ) + msgs = msgs.map((msg: any) => { + return Array.isArray(msg) ? msg[0] : msg + }) + } + + const txOptions: CreateTxOptions = { + msgs, + memo: undefined, + gasPrices: `${gasPrice}${feeTokenInfo?.contract_addr}`, + ...additionalOptions, + } + + return txOptions + } catch (error) { + console.log(error) + } + return undefined + }, + [ + feeTokenInfo, + from, + gasPrice, + generateContractMessages, + lpContract, + profitableQuery, + slippageTolerance, + to, + tokenInfo1?.decimals, + type, + walletAddress, + ] + ) + + useEffect(() => { + let isAborted = false + + const { value1, value2 } = formData + + generateCreateTxOptions({ value1, value2 }).then((res) => { + if (isAborted) { + return + } + + setCreateTxOptions(res) + }) + + return () => { + isAborted = true + } + }, [formData, generateCreateTxOptions]) + + const { fee, isCalculating: isFeeCalculating } = useFee(createTxOptions) + const feeAmount = useMemo(() => { + if (!feeTokenInfo?.contract_addr) { + return undefined + } + return `${fee?.amount?.get(feeTokenInfo?.contract_addr)?.amount.toDP()}` + }, [fee, feeTokenInfo]) + + useEffect(() => { + trigger(Key.value1) + }, [trigger, feeAmount]) + const simulationContents = useMemo(() => { if ( !( @@ -367,13 +548,11 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { ? calc.minimumReceived({ expectedAmount: `${profitableQuery?.simulatedAmount}`, max_spread: String(slippageTolerance), - commission: find(infoKey, formData[Key.symbol2]), + commission: "0", decimals: tokenInfo1?.decimals, }) : "0" - const taxs = tax.filter((coin) => !coin.amount.equals(0)) - return [ ...insertIf(type === Type.SWAP, { title: Rate, @@ -425,28 +604,15 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { ), }), - { + ...insertIf(walletAddress && formState?.isValid, { title: Tx Fee, - content: ( + content: isFeeCalculating ? ( + "Calculating..." + ) : ( - {lookup(formData[Key.feeValue])} + {feeAmount ? feeAmount : "-"} ), - }, - ...insertIf(taxs.toArray().length > 0, { - title: `Tax`, - content: taxs.toArray().map((coin, index) => { - return index === 0 ? ( - {lookup(coin.amount.toString())} - ) : ( -
- , - - {lookup(coin.amount.toString())} - -
- ) - }), }), ...insertIf(type === Type.SWAP && spread !== "", { title: Spread, @@ -484,172 +650,29 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { }), ] }, [ + feeAmount, formData, - type, + formState, + isFeeCalculating, + lpContract, + poolResult, profitableQuery, slippageTolerance, - find, - tokenInfo1?.decimals, - tax, - poolResult, - lpContract, spread, + tokenInfo1?.decimals, tokenInfos, + type, + walletAddress, ]) - const getMsgs = useCallback( - ( - _msg: any, - { - amount, - token, - minimumReceived, - beliefPrice, - }: { - amount?: string | number - token?: string - minimumReceived?: string | number - beliefPrice?: string | number - } - ) => { - const msg = Array.isArray(_msg) ? _msg[0] : _msg - - if (msg?.execute_msg?.swap) { - msg.execute_msg.swap.belief_price = `${beliefPrice}` - } - if (msg?.execute_msg?.send?.msg?.swap) { - msg.execute_msg.send.msg.swap.belief_price = `${beliefPrice}` - } - if (msg?.execute_msg?.send?.msg?.execute_swap_operations) { - msg.execute_msg.send.msg.execute_swap_operations.minimum_receive = - parseInt(`${minimumReceived}`, 10).toString() - if (isNativeToken(token || "")) { - msg.coins = Coins.fromString(toAmount(`${amount}`) + token) - } - - msg.execute_msg.send.msg = btoa( - JSON.stringify(msg.execute_msg.send.msg) - ) - } else if (msg?.execute_msg?.send?.msg) { - msg.execute_msg.send.msg = btoa( - JSON.stringify(msg.execute_msg.send.msg) - ) - } - if (msg?.execute_msg?.execute_swap_operations) { - msg.execute_msg.execute_swap_operations.minimum_receive = parseInt( - `${minimumReceived}`, - 10 - ).toString() - msg.execute_msg.execute_swap_operations.offer_amount = toAmount( - `${amount}`, - token - ) - - if (isNativeToken(token || "")) { - msg.coins = Coins.fromString(toAmount(`${amount}`) + token) - } - } - return [msg] - }, - [isNativeToken] - ) - - const { gasPrice } = useGasPrice(formData[Key.feeSymbol]) - const getTax = useCallback( - async ({ - value1, - value2, - token1, - token2, - }: { - value1?: string - value2?: string - token1?: string - token2?: string - }) => { - let newTax = tax - - newTax.map((coin) => { - if ( - !( - coin.denom === token1 || - (type === Type.PROVIDE && coin.denom === token2) - ) - ) { - newTax.set(coin.denom, 0) - } - - return true - }) - - const taxRate = await loadTaxRate() - if (token1 && hasTaxToken(token1) && taxRate && value1) { - const taxCap1 = await loadTaxInfo(token1) - if (taxCap1) { - const tax1 = calcTax(toAmount(value1), taxCap1, taxRate) - newTax.set(token1, tax1) - } - } - if ( - type === Type.PROVIDE && - token2 && - hasTaxToken(token2) && - taxRate && - value2 - ) { - const taxCap2 = await loadTaxInfo(token2) - if (taxCap2) { - const tax2 = calcTax(toAmount(value2), taxCap2, taxRate) - newTax.set(token2, tax2) - } - } - return newTax - }, - [type, loadTaxInfo, loadTaxRate, tax] - ) - - const isTaxCalculating = useRef(false) - useEffect(() => { - if (isTaxCalculating?.current) { - return - } - isTaxCalculating.current = true - getTax({ - value1: formData[Key.value1], - value2: formData[Key.value2], - token1: from, - token2: to, - }) - .then((value) => { - setTax(value) - }) - .catch(() => { - setTax(tax) - }) - .finally(() => { - isTaxCalculating.current = false - }) - }, [formData, tax, getTax, from, to]) - const validateForm = async ( - key: Key.value1 | Key.value2 | Key.feeValue | Key.feeSymbol | Key.load, + key: Key.value1 | Key.value2 | Key.feeSymbol | Key.load, newValues?: Partial ) => { - const { - value1, - value2, - symbol1, - symbol2, - max1, - max2, - feeValue, - feeSymbol, - maxFee, - } = { ...formData, ...(newValues || {}) } + const { value1, value2, symbol1, symbol2, max1, max2, feeSymbol, maxFee } = + { ...formData, ...(newValues || {}) } if (key === Key.value1) { - const taxCap = await loadTaxInfo(from) - const taxRate = await loadTaxRate() return ( v.amount(value1, { symbol: symbol1, @@ -657,14 +680,11 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { refvalue: value2, refsymbol: symbol2, isFrom: true, - feeValue, + feeValue: feeAmount, feeSymbol, maxFee, - taxCap, - taxRate, type, decimals: tokenInfo1?.decimals, - token: from, }) || true ) } @@ -686,7 +706,6 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { maxFee: "0", type, decimals: tokenInfo2?.decimals, - token: to, }) || true ) } @@ -825,14 +844,6 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { trigger, profitableQuery, ]) - useEffect(() => { - setValue(Key.gasPrice, gasPrice || "") - setValue(Key.feeValue, gasPrice ? ceil(times(fee.gas, gasPrice)) : "") - }, [fee.gas, gasPrice, setValue]) - - useEffect(() => { - setValue(Key.feeValue, ceil(times(fee?.gas, gasPrice)) || "") - }, [fee, gasPrice, setValue]) const handleFailure = useCallback(() => { setTimeout(() => { @@ -845,113 +856,37 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { window.location.reload() }, [form]) - const handleSubmit = useCallback>>>( - async (values) => { - const { value1, value2, feeSymbol, gasPrice } = values - try { - settingsModal.close() - - let msgs: any = {} - if (type === Type.SWAP) { - if (!profitableQuery?.msg) { - return - } - msgs = getMsgs(profitableQuery?.msg, { - amount: `${value1}`, - minimumReceived: profitableQuery - ? calc.minimumReceived({ - expectedAmount: `${profitableQuery?.simulatedAmount}`, - max_spread: String(slippageTolerance), - commission: find(infoKey, formData[Key.symbol2]), - decimals: tokenInfo1?.decimals, - }) - : "0", - token: from, - beliefPrice: `${decimal( - times( - div(value1, value2), - Math.pow( - 10, - (tokenInfo1?.decimals || 0) - (tokenInfo2?.decimals || 0) - ) || 1 - ), - 18 - )}`, - }) - } else { - msgs = await generateContractMessages( - { - [Type.PROVIDE]: { - type: Type.PROVIDE, - sender: `${walletAddress}`, - fromAmount: `${value1}`, - toAmount: `${value2}`, - from: `${from}`, - to: `${to}`, - slippage: slippageTolerance, - }, - [Type.WITHDRAW]: { - type: Type.WITHDRAW, - sender: `${walletAddress}`, - amount: `${value1}`, - lpAddr: `${lpContract}`, - }, - }[type] as any - ) - msgs = msgs.map((msg: any) => { - return Array.isArray(msg) ? msg[0] : msg - }) - } - - let txOptions: CreateTxOptions = { - msgs, - memo: undefined, - gasPrices: `${gasPrice}${getSymbol(feeSymbol || "")}`, - } - - const signMsg = await terra.tx.create( - [{ address: walletAddress }], - txOptions - ) - txOptions.fee = signMsg.auth_info.fee + const handleSubmit = useCallback(async () => { + try { + settingsModal.close() + if (!createTxOptions || !fee) { + return + } - const extensionResult = await terraExtensionPost(txOptions) + const extensionResult = await terraExtensionPost({ + ...createTxOptions, + fee, + }) - if (extensionResult) { - setResult(extensionResult) - return - } - } catch (error) { - console.error(error) - setResult(error as any) + if (extensionResult) { + setResult(extensionResult) + return } - }, - [ - settingsModal, - type, - getSymbol, - terra, - walletAddress, - terraExtensionPost, - generateContractMessages, - from, - to, - slippageTolerance, - tokenInfo1, - tokenInfo2, - getMsgs, - profitableQuery, - find, - formData, - lpContract, - ] - ) + } catch (error) { + console.error(error) + setResult(error as any) + } + }, [createTxOptions, fee, settingsModal, terraExtensionPost]) const [result, setResult] = useState() - + // hotfix: prevent modal closing when virtual keyboard is opened + const lastWindowWidth = useRef(window.innerWidth) useEffect(() => { const handleResize = () => { - settingsModal.close() + if (lastWindowWidth.current !== window.innerWidth) { + settingsModal.close() + } + lastWindowWidth.current = window.innerWidth } window.addEventListener("resize", handleResize) return () => { @@ -959,6 +894,88 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { } }, [settingsModal]) + useEffect(() => { + let isAborted = false + const adjustMaxBalance = async () => { + const { value1, value2 } = formData + try { + if ( + type !== Type.WITHDRAW && + formData[Key.symbol1] === formData[Key.feeSymbol] && + balance1 && + feeTokenInfo && + formData[Key.value1] === lookup(balance1, feeTokenInfo?.contract_addr) + ) { + const txOptions = await generateCreateTxOptions( + { + value1, + value2, + }, + { gasAdjustment: 2 } + ) + if (isAborted) { + return + } + if (txOptions) { + const calculatedFee = await calculateFee( + terra, + walletAddress, + txOptions + ) + + if (isAborted) { + return + } + + const maxFeeAmount = `${ + calculatedFee?.amount + ?.get(feeTokenInfo?.contract_addr) + ?.amount?.toDP?.() || "" + }` + + if (maxFeeAmount) { + setValue( + Key.value1, + minus( + value1, + lookup(maxFeeAmount, feeTokenInfo?.contract_addr) + ), + { shouldDirty: true, shouldTouch: true, shouldValidate: true } + ) + } + } + } + } catch (error) { + console.log(error) + } + } + + adjustMaxBalance() + + return () => { + isAborted = true + } + }, [ + balance1, + feeTokenInfo, + formData, + generateCreateTxOptions, + setValue, + terra, + type, + walletAddress, + ]) + + useEffect(() => { + if (lt(formData[Key.value1], 0)) { + setValue(Key.value1, "0") + } + + if (lt(formData[Key.value2], 0)) { + setValue(Key.value2, "0") + } + }, [formData, setValue]) + return ( @@ -1065,40 +1082,21 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { unit={selectToken1.button} assets={selectToken1.assets} focused={selectToken1.isOpen} + isLoading={ + !!formData[Key.symbol1] && + !!formData[Key.symbol2] && + formData[Key.symbol1] === formData[Key.feeSymbol] && + formData[Key.value1] === + lookup(balance1, feeTokenInfo?.contract_addr) + } max={ formData[Key.symbol1] ? async () => { - if (type === Type.WITHDRAW) { - setValue(Key.value1, lookup(formData[Key.max1], from)) - trigger(Key.value1) - return - } - let taxVal = "0" - const taxs = await getTax({ - token1: from, - value1: lookup(formData[Key.max1], from), - }) - - taxs.map((tax) => { - if (tax.denom === from) { - taxVal = tax.toData().amount - return false - } - return true + setValue(Key.value1, lookup(balance1, from), { + shouldValidate: true, + shouldDirty: true, + shouldTouch: true, }) - let maxBalance = minus(formData[Key.max1], taxVal) - // fee - if (formData[Key.symbol1] === formData[Key.feeSymbol]) { - if (gte(maxBalance, formData[Key.feeValue])) { - maxBalance = minus(maxBalance, formData[Key.feeValue]) - } else { - maxBalance = minus(maxBalance, maxBalance) - } - } - - maxBalance = lookup(maxBalance, from) - setValue(Key.value1, maxBalance) - trigger(Key.value1) } : undefined } @@ -1147,8 +1145,6 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { }), autoComplete: "off", readOnly: true, - // [Type.PROVIDE, Type.WITHDRAW].includes(type) || - // (!isReversed && isAutoRouterLoading), onKeyDown: () => { setIsReversed(true) }, @@ -1218,7 +1214,7 @@ const SwapForm = ({ type, tabs }: { type: Type; tabs: TabViewProps }) => { - + ) } diff --git a/src/forms/SwapFormGroup.tsx b/src/forms/SwapFormGroup.tsx index 84c6facf..020b5e21 100644 --- a/src/forms/SwapFormGroup.tsx +++ b/src/forms/SwapFormGroup.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react" +import { useEffect, useRef, useState } from "react" import classNames from "classnames/bind" import styles from "./SwapFormGroup.module.scss" diff --git a/src/forms/SwapResultContents.tsx b/src/forms/SwapResultContents.tsx index 78dedc51..b6b24592 100644 --- a/src/forms/SwapResultContents.tsx +++ b/src/forms/SwapResultContents.tsx @@ -1,4 +1,3 @@ -import React from "react" import { SwapAttribute } from "types/swapTx" import useSwapResults from "../hooks/useSwapResults" import ConfirmDetails from "./ConfirmDetails" diff --git a/src/forms/SwapSelectToken.tsx b/src/forms/SwapSelectToken.tsx index ce6138b5..4f8993e9 100644 --- a/src/forms/SwapSelectToken.tsx +++ b/src/forms/SwapSelectToken.tsx @@ -2,17 +2,19 @@ import { FC, PropsWithChildren } from "react" import MESSAGE from "../lang/MESSAGE.json" import { lookupSymbol } from "../libs/parse" import Icon from "../components/Icon" -import { Config } from "./useSelectAsset" import styles from "./SwapSelectToken.module.scss" import { GetTokenSvg } from "../helpers/token" import { lpTokenInfos, tokenInfos } from "../rest/usePairs" import { Type } from "../pages/Swap" -interface Props extends Config { +interface Props { isOpen: boolean asset?: string type: string onClick: () => void + value: string + onSelect: (asset: string) => void + formatTokenName?: (symbol: string) => string } const SwapSelectToken: FC> = ({ diff --git a/src/forms/SwapToken.tsx b/src/forms/SwapToken.tsx index f2c80b67..3f65d1c8 100644 --- a/src/forms/SwapToken.tsx +++ b/src/forms/SwapToken.tsx @@ -1,9 +1,8 @@ -import React from "react" import { gt } from "../libs/math" import { format, lookupSymbol } from "../libs/parse" import styles from "./SwapToken.module.scss" import { GetTokenSvg } from "../helpers/token" -import { useContractsAddress } from "hooks/useContractsAddress" +import { isNativeToken } from "libs/utils" interface Props extends AssetItem { contract_addr?: string @@ -43,7 +42,6 @@ const SwapToken = ({ highlightString = "", }: Props) => { const symbols = symbol.split("-") - const { isNativeToken } = useContractsAddress() return (
diff --git a/src/forms/SwapTokens.tsx b/src/forms/SwapTokens.tsx index 773becb8..ed18acbb 100644 --- a/src/forms/SwapTokens.tsx +++ b/src/forms/SwapTokens.tsx @@ -1,39 +1,64 @@ import { FC, useEffect, useMemo, useRef, useState } from "react" import classNames from "classnames/bind" -import { useCombineKeys } from "../hooks" -import { Config } from "./useSelectAsset" import SwapToken from "./SwapToken" import styles from "./SwapTokens.module.scss" -import { lpTokenInfos } from "../rest/usePairs" +import usePairs, { lpTokenInfos } from "../rest/usePairs" import { Type } from "../pages/Swap" import { tokenInfos } from "../rest/usePairs" import Loading from "components/Loading" import { SwapTokenAsset } from "./useSwapSelectToken" import { VariableSizeList, ListChildComponentProps } from "react-window" -import { useContractsAddress } from "hooks/useContractsAddress" +import { isNativeToken } from "libs/utils" +import styled from "styled-components" const cx = classNames.bind(styles) -interface Props extends Config { +interface Props { isFrom: boolean selected?: string onSelect: (asset: string, isUnable?: boolean) => void type: string assetList?: SwapTokenAsset[] + value: string + formatTokenName?: (symbol: string) => string } +const NoPairs = styled.div` + width: 100%; + height: 100%; + position: relative; + font-size: 16px; + font-weight: bold; + font-stretch: normal; + font-style: normal; + line-height: normal; + letter-spacing: normal; + text-align: center; + color: #0222ba; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + + & > * { + margin-bottom: 20px; + } + + & > h1 { + font-size: 46px; + font-weight: bold; + } +` + const SwapTokens = ({ selected, onSelect: handleSelect, type, assetList, - priceKey, - balanceKey, formatTokenName, }: Props) => { const listRef = useRef(null) - const { loading } = useCombineKeys([priceKey, balanceKey]) - const { isNativeToken } = useContractsAddress() + const { isLoading: isPairsLoading } = usePairs() /* search */ const [searchKeyword, setSearchKeyword] = useState("") @@ -121,20 +146,33 @@ const SwapTokens = ({ /> -
    - {assetElements ? ( - - isNativeToken(filteredAssetList?.[index].contract_addr || "") - ? 75 - : 75 - } - itemCount={assetElements.length} - > - {Row} - +
      + {assetElements && !isPairsLoading ? ( + <> + {assetElements?.length ? ( + + isNativeToken(filteredAssetList?.[index].contract_addr || "") + ? 75 + : 75 + } + itemCount={assetElements.length} + > + {Row} + + ) : ( + +

      :(

      +
      + No available pairs yet. +
      + We are looking forward to getting the first providing! +
      +
      + )} + ) : (
      - +
      )}
    diff --git a/src/forms/SwapTxHash.tsx b/src/forms/SwapTxHash.tsx index f5840753..51e36370 100644 --- a/src/forms/SwapTxHash.tsx +++ b/src/forms/SwapTxHash.tsx @@ -1,14 +1,13 @@ -import React from "react" import { truncate } from "../libs/text" import { useNetwork } from "../hooks" import ExtLink from "../components/ExtLink" import styles from "./SwapTxHash.module.scss" const TxHash = ({ children: hash }: { children: string }) => { - const { finder } = useNetwork() + const { getFinderUrl } = useNetwork() return ( - + {truncate(hash, [8, 8])} ) diff --git a/src/forms/SwapTxInfo.tsx b/src/forms/SwapTxInfo.tsx index 2a6f6e8d..67bdc291 100644 --- a/src/forms/SwapTxInfo.tsx +++ b/src/forms/SwapTxInfo.tsx @@ -3,10 +3,11 @@ import ConfirmDetails from "./ConfirmDetails" import TxHash from "./SwapTxHash" import { tokenInfos } from "../rest/usePairs" import { formatAsset } from "../libs/parse" -import { SwapAttribute, SwapTxInfo } from "types/swapTx" +import { SwapAttribute } from "types/swapTx" +import { TxInfo as ITxInfo } from "@terra-money/terra.js" interface Props { - txInfo: SwapTxInfo + txInfo: ITxInfo parserKey: string } @@ -20,8 +21,11 @@ const TxInfo = ({ txInfo, parserKey }: Props) => { contents.push([ { title: "Fee", - content: tx.value.fee.amount.map((value) => { - return formatAsset(value.amount, tokenInfos.get(value.denom)?.symbol) + content: tx.auth_info.fee.amount.map((coin) => { + return formatAsset( + String(coin.amount), + tokenInfos.get(coin.denom)?.symbol + ) }), }, ]) @@ -79,8 +83,7 @@ const TxInfo = ({ txInfo, parserKey }: Props) => { const commission = fromContract.find( ({ key }) => key === "commission_amount" ) - const tax = fromContract.find(({ key }) => key === "tax_amount") - + if (offerAsset && offerAmount) { let value = formatAsset( offerAmount.value, @@ -90,11 +93,8 @@ const TxInfo = ({ txInfo, parserKey }: Props) => { } if (askAsset && returnAmount) { const symbol = tokenInfos.get(askAsset.value)?.symbol - let taxAmount = BigInt(0) - if (tax) { - taxAmount = BigInt(tax.value) - } - const toAmount = BigInt(returnAmount.value) - taxAmount + + const toAmount = BigInt(returnAmount.value) let value = formatAsset(toAmount.toString(), symbol) reconstructed.push({ key: "To", value: value }) @@ -110,12 +110,6 @@ const TxInfo = ({ txInfo, parserKey }: Props) => { value: formatAsset(commission.value, symbol), }) } - if (tax) { - reconstructed.push({ - key: "* Tax", - value: formatAsset(tax.value, symbol), - }) - } } } else if (parserKey === "Provide") { const action = fromContract.find( diff --git a/src/forms/TxHash.tsx b/src/forms/TxHash.tsx index b44ff71a..3db2cfbf 100644 --- a/src/forms/TxHash.tsx +++ b/src/forms/TxHash.tsx @@ -1,14 +1,13 @@ -import React from "react" import { truncate } from "../libs/text" import { useNetwork } from "../hooks" import ExtLink from "../components/ExtLink" import styles from "./TxHash.module.scss" const TxHash = ({ children: hash }: { children: string }) => { - const { finder } = useNetwork() + const { getFinderUrl } = useNetwork() return ( - + {truncate(hash, [10, 10])} ) diff --git a/src/forms/formHelpers.ts b/src/forms/formHelpers.ts index 11495381..dc337b17 100644 --- a/src/forms/formHelpers.ts +++ b/src/forms/formHelpers.ts @@ -1,9 +1,8 @@ import { AccAddress } from "@terra-money/terra.js" import MESSAGE from "lang/MESSAGE.json" -import { ceil, gt, gte, lte, min, times, minus, plus } from "libs/math" +import { gt, gte, lte, plus } from "libs/math" import { getLength, omitEmpty } from "libs/utils" import { lookup, format, toAmount, formatAsset, validateDp } from "libs/parse" -import { hasTaxToken } from "helpers/token" import { Type } from "pages/Swap" import { Buffer } from "buffer" @@ -42,14 +41,11 @@ interface AmountRange { refvalue?: string refsymbol?: string isFrom?: boolean - taxCap?: string - taxRate?: string feeValue?: string feeSymbol?: string maxFee?: string type?: string decimals?: number - token?: string } export const validate = { @@ -86,26 +82,17 @@ export const validate = { refvalue, refsymbol, isFrom, - taxCap, - taxRate, feeValue, feeSymbol, maxFee, type, decimals, - token, } = range const amount = symbol ? toAmount(value, symbol) : value - let tax = "0" - - if (symbol && taxRate && taxCap && token && hasTaxToken(token)) { - tax = calcTax(amount, taxCap, taxRate) - } if ( - maxFee === "" || - maxFee === undefined || - feeValue === undefined || + feeValue !== undefined && + maxFee !== undefined && gt(feeValue, maxFee) ) { return `You don't have enough balance to pay for ${formatAsset( @@ -146,11 +133,6 @@ export const validate = { symbol === feeSymbol && gt(plus(amount, feeValue), max) ? `Balance is insufficient due to the fee(${lookup(feeValue, feeSymbol)})` - : ((type !== Type.PROVIDE && isFrom === true) || type === Type.PROVIDE) && - ((symbol !== feeSymbol && gt(minus(tax, minus(max, amount)), 0)) || - (symbol === feeSymbol && - gt(minus(tax, minus(max, plus(amount, feeValue))), 0))) - ? `You must leave at least ${format(tax, symbol)} ${symbol} tax value` : refvalue === "0" && refsymbol !== "" ? "Not enough pool balance" : "" @@ -166,18 +148,13 @@ export const validate = { }, } -export const calcTax = (amount: string, taxCap: string, taxRate: string) => { - if (taxCap === "") { - return ceil(times(amount, taxRate)) - } - - return ceil(min([times(amount, taxRate), taxCap])) -} - /* data (utf-8) */ -export const toBase64 = (object: object) => { +export const toBase64 = (object: object | string) => { try { - return Buffer.from(JSON.stringify(omitEmpty(object))).toString("base64") + if (typeof object === "object") { + return Buffer.from(JSON.stringify(omitEmpty(object))).toString("base64") + } + return Buffer.from(object).toString("base64") } catch (error) { return "" } diff --git a/src/forms/useSelectAsset.tsx b/src/forms/useSelectAsset.tsx deleted file mode 100644 index 6d7618ff..00000000 --- a/src/forms/useSelectAsset.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useState } from "react" -import { PriceKey, BalanceKey } from "../hooks/contractKeys" -import SelectAsset from "./SelectAsset" -import Assets from "./Assets" - -export interface Config { - /** Current value */ - value: string - /** Function to call when a value is selected */ - onSelect: (asset: string) => void - /** Key of price to show from data */ - priceKey?: PriceKey - /** Key of balance to show from data */ - balanceKey?: BalanceKey - /** Include UST in the list */ - useUST?: boolean - /** Exclude symbol in the list */ - skip?: string[] - /** Modify token name */ - formatTokenName?: (symbol: string) => string -} - -export default (config: Config) => { - const { value, onSelect } = config - const [isOpen, setIsOpen] = useState(false) - const toggle = () => (isOpen ? handleSelect(value) : setIsOpen(!isOpen)) - - /* select asset */ - const handleSelect = (asset: string) => { - onSelect(asset) - setIsOpen(false) - } - - const select = { ...config, isOpen, asset: value, onClick: toggle } - - return { - isOpen, - button: , - assets: isOpen ? ( - - ) : undefined, - } -} diff --git a/src/graphql/alias.ts b/src/graphql/alias.ts deleted file mode 100644 index ca737418..00000000 --- a/src/graphql/alias.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { gql } from "@apollo/client" -import { WASMQUERY } from "./gqldocs" - -interface Query extends Partial { - token: string -} - -const alias = ({ token, contract, msg }: Query) => - !msg - ? `` - : ` - ${token}: ${WASMQUERY}( - ContractAddress: "${contract}" - QueryMsg: "${stringify(msg)}" - ) { - Height - Result - }` - -export default (queries: Query[]) => gql` - query { - ${queries.map(alias)} - } -` - -export const stringify = (msg: object) => { - const stringify = JSON.stringify(msg) - return stringify.replace(/"/g, '\\"') -} diff --git a/src/graphql/gqldocs.ts b/src/graphql/gqldocs.ts deleted file mode 100644 index e957f5ff..00000000 --- a/src/graphql/gqldocs.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { gql } from "@apollo/client" - -export const WASMQUERY = "WasmContractsContractAddressStore" - -export const CONTRACT = gql` - query($contract: String, $msg: String) { - WasmContractsContractAddressStore( - ContractAddress: $contract - QueryMsg: $msg - ) { - Height - Result - } - } -` - -export const TAX = gql` - query { - TreasuryTaxRate { - Result - } - - TreasuryTaxCapDenom(Denom: "uusd") { - Result - } - } -` - -export const TXINFOS = gql` - query($hash: String) { - TxInfos(TxHash: $hash) { - TxHash - - Tx { - Fee { - Amount { - Amount - Denom - } - } - Memo - } - - Logs { - Events { - Type - Attributes { - Key - Value - } - } - } - } - } -` diff --git a/src/graphql/queries/useBankBalances.ts b/src/graphql/queries/useBankBalances.ts deleted file mode 100644 index 4e62d7e6..00000000 --- a/src/graphql/queries/useBankBalances.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { gql, useLazyQuery } from "@apollo/client" - -const QUERY = gql` - query($address: String) { - BankBalancesAddress(Address: $address) { - Result { - Amount - Denom - } - } - } -` - -export default (address: string) => { - const [load, result] = useLazyQuery(QUERY, { variables: { address } }) - return { load, ...result } -} diff --git a/src/graphql/queries/useGovStake.ts b/src/graphql/queries/useGovStake.ts deleted file mode 100644 index ca85ca36..00000000 --- a/src/graphql/queries/useGovStake.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useContractsAddress } from "hooks/useContractsAddress" -import { useLazyContractQuery } from "../useContractQuery" - -export default (address: string) => { - const { contracts } = useContractsAddress() - const variables = { contract: contracts["gov"], msg: { staker: { address } } } - const query = useLazyContractQuery(variables) - return query -} diff --git a/src/graphql/queries/useLpTokenBalance.ts b/src/graphql/queries/useLpTokenBalance.ts deleted file mode 100644 index 6e51cf2c..00000000 --- a/src/graphql/queries/useLpTokenBalance.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useLazyContractQueries } from "../useContractQueries" - -export default (address: string) => { - const generate = ({ lpToken }: ListedItem) => { - return { contract: lpToken, msg: { balance: { address } } } - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/useLpTokenInfo.ts b/src/graphql/queries/useLpTokenInfo.ts deleted file mode 100644 index 74a060a1..00000000 --- a/src/graphql/queries/useLpTokenInfo.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useLazyContractQueries } from "../useContractQueries" - -export default () => { - const generate = ({ lpToken }: ListedItem) => { - return { contract: lpToken, msg: { token_info: {} } } - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/useMintInfo.ts b/src/graphql/queries/useMintInfo.ts deleted file mode 100644 index 8503a31f..00000000 --- a/src/graphql/queries/useMintInfo.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { MIR } from "constants/constants" -import { useLazyContractQueries } from "graphql/useContractQueries" -import { useContractsAddress } from "hooks/useContractsAddress" - -export default () => { - const { contracts } = useContractsAddress() - const generate = ({ token, symbol }: ListedItem) => { - const variables = { - contract: contracts["mint"], - msg: { asset_config: { asset_token: token } }, - } - - return symbol === MIR ? undefined : variables - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/useMintPositions.ts b/src/graphql/queries/useMintPositions.ts deleted file mode 100644 index 440ec1be..00000000 --- a/src/graphql/queries/useMintPositions.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useContractsAddress } from "hooks/useContractsAddress" -import { useLazyContractQuery } from "../useContractQuery" - -export default (address: string) => { - const { contracts } = useContractsAddress() - const variables = { - contract: contracts["mint"], - msg: { positions: { owner_addr: address, limit: Math.pow(2, 32) - 1 } }, - } - - const query = useLazyContractQuery(variables) - return query -} diff --git a/src/graphql/queries/useOraclePrice.ts b/src/graphql/queries/useOraclePrice.ts deleted file mode 100644 index 6943b426..00000000 --- a/src/graphql/queries/useOraclePrice.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { MIR } from "constants/constants" -import { useLazyContractQueries } from "graphql/useContractQueries" -import { useContractsAddress } from "hooks/useContractsAddress" - -export default () => { - const { contracts } = useContractsAddress() - const generate = ({ token, symbol }: ListedItem) => { - const variables = { - contract: contracts["oracle"], - msg: { price: { asset_token: token } }, - } - - return symbol === MIR ? undefined : variables - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/usePairConfig.ts b/src/graphql/queries/usePairConfig.ts deleted file mode 100644 index 2bf295cf..00000000 --- a/src/graphql/queries/usePairConfig.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useLazyContractQueries } from "../useContractQueries" - -export default () => { - const generate = ({ token, pair }: ListedItem) => { - return { token, contract: pair, msg: { config_swap: {} } } - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/usePairPool.ts b/src/graphql/queries/usePairPool.ts deleted file mode 100644 index 70ce7a6c..00000000 --- a/src/graphql/queries/usePairPool.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useLazyContractQueries } from "../useContractQueries" - -export default () => { - const generate = ({ token, pair }: ListedItem) => { - return { token, contract: pair, msg: { pool: {} } } - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/useStakingPool.ts b/src/graphql/queries/useStakingPool.ts deleted file mode 100644 index 8d8d0854..00000000 --- a/src/graphql/queries/useStakingPool.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useContractsAddress } from "hooks/useContractsAddress" -import { useLazyContractQueries } from "../useContractQueries" - -export default () => { - const { contracts } = useContractsAddress() - const generate = ({ token }: ListedItem) => ({ - contract: contracts["staking"], - msg: { pool_info: { asset_token: token } }, - }) - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/queries/useStakingReward.ts b/src/graphql/queries/useStakingReward.ts deleted file mode 100644 index d6bea1c3..00000000 --- a/src/graphql/queries/useStakingReward.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useContractsAddress } from "hooks/useContractsAddress" -import { useLazyContractQuery } from "../useContractQuery" - -export default (address: string) => { - const { contracts } = useContractsAddress() - const variables = { - contract: contracts["staking"], - msg: { reward_info: { staker: address } }, - } - - const query = useLazyContractQuery(variables) - return query -} diff --git a/src/graphql/queries/useTokenBalance.ts b/src/graphql/queries/useTokenBalance.ts deleted file mode 100644 index bde02c97..00000000 --- a/src/graphql/queries/useTokenBalance.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useLazyContractQueries } from "../useContractQueries" - -export default (address: string) => { - const generate = ({ token }: ListedItem) => { - return { contract: token, msg: { balance: { address } } } - } - - const query = useLazyContractQueries(generate) - return query -} diff --git a/src/graphql/response.ts b/src/graphql/response.ts deleted file mode 100644 index 9938317e..00000000 --- a/src/graphql/response.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Dictionary } from "ramda" - -export const parseResult = (params: { Result?: string } | null) => - params && params.Result ? (JSON.parse(params.Result) as Parsed) : undefined - -/* alias */ -export const parseResults = (object?: Dictionary) => - object && - Object.entries(object).reduce>((acc, [token, data]) => { - const next = parseResult(data) - return Object.assign({}, acc, next && { [token]: next }) - }, {}) diff --git a/src/graphql/useContractQueries.ts b/src/graphql/useContractQueries.ts deleted file mode 100644 index ffa0d965..00000000 --- a/src/graphql/useContractQueries.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Dictionary } from "ramda" -import { useQuery, useLazyQuery } from "@apollo/client" -import alias from "./alias" -import { parseResults } from "./response" -import { useContractsAddress } from "hooks/useContractsAddress" - -type GenerateVariables = (item: ListedItem) => ContractVariables | undefined - -export const useLazyContractQueries = (generate: GenerateVariables) => { - const query = useGenerateQuery(generate) - const [load, result] = useLazyQuery>(query) - return { result: { load, ...result }, parsed: parse(result) } -} - -export default (generate: GenerateVariables) => { - const query = useGenerateQuery(generate) - const result = useQuery>(query) - return { result, parsed: parse(result) } -} - -/* helpers */ -const useGenerateQuery = (generate: GenerateVariables) => { - const { listed } = useContractsAddress() - return alias(listed.map((item) => ({ token: item.token, ...generate(item) }))) -} - -const parse = ({ data }: { data?: Dictionary }) => - data && parseResults(data) diff --git a/src/graphql/useContractQuery.ts b/src/graphql/useContractQuery.ts deleted file mode 100644 index 0de6f1b5..00000000 --- a/src/graphql/useContractQuery.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useQuery, useLazyQuery } from "@apollo/client" -import { CONTRACT, WASMQUERY } from "./gqldocs" -import { parseResult } from "./response" - -export const useLazyContractQuery = (params: ContractVariables) => { - const variables = generateVariables(params) - const [load, result] = useLazyQuery(CONTRACT, { variables }) - return { result: { load, ...result }, parsed: parse(result) } -} - -export default (params: ContractVariables) => { - const variables = generateVariables(params) - const result = useQuery(CONTRACT, { variables }) - return { result, parsed: parse(result) } -} - -/* helpers */ -const generateVariables = ({ contract, msg }: ContractVariables) => { - return { contract, msg: JSON.stringify(msg) } -} - -const parse = ({ data }: { data?: ContractsData }) => - data && parseResult(data[WASMQUERY]) diff --git a/src/graphql/useGov.ts b/src/graphql/useGov.ts deleted file mode 100644 index 9c2ea728..00000000 --- a/src/graphql/useGov.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { useEffect } from "react" -import { Dictionary } from "ramda" -import { QueryResult } from "@apollo/client" -import { number } from "../libs/math" -import createContext from "../hooks/createContext" -import { fromBase64 } from "../forms/formHelpers" -import { WASMQUERY } from "./gqldocs" -import useContractQuery from "./useContractQuery" -import { useContractsAddress } from "hooks/useContractsAddress" - -export enum GovKey { - /** Config: Call it once for the first time */ - CONFIG = "config", - STATE = "state", - BALANCE = "balance", - POLLS = "polls", -} - -interface Gov { - result: Record - [GovKey.CONFIG]: GovConfig | undefined - [GovKey.STATE]: GovState | undefined - [GovKey.BALANCE]: string | undefined - [GovKey.POLLS]: { data: Dictionary; list: number[]; height?: number } -} - -export const [useGov, GovProvider] = createContext("useGov") - -/* state */ -export const useGovContext = (): Gov => { - const config = useGovConfig() - const state = useGovState() - const balance = useMirrorBalance() - const { result, polls } = usePolls() - const { height } = polls - - return { - result: { - [GovKey.CONFIG]: config.result, - [GovKey.STATE]: state.result, - [GovKey.BALANCE]: balance.result, - [GovKey.POLLS]: result, - }, - - [GovKey.CONFIG]: config.parsed, - [GovKey.STATE]: state.parsed, - [GovKey.BALANCE]: balance.parsed?.balance, - [GovKey.POLLS]: { ...polls, height: height ? number(height) : undefined }, - } -} - -/* refetch gov */ -export const useRefetchGov = (keys: GovKey[]) => { - const { result } = useGov() - useEffect(() => { - keys.forEach((key) => { - const { refetch } = result[key] - refetch() - }) - // eslint-disable-next-line - }, [JSON.stringify(keys)]) -} - -/* config */ -const useGovConfig = () => { - const { contracts } = useContractsAddress() - const variables = { contract: contracts["gov"], msg: { config: {} } } - const query = useContractQuery(variables) - return query -} - -/* state */ -const useGovState = () => { - const { contracts } = useContractsAddress() - const variables = { contract: contracts["gov"], msg: { state: {} } } - const query = useContractQuery(variables) - return query -} - -/* mirror balance */ -const useMirrorBalance = () => { - const { contracts } = useContractsAddress() - const variables = { - contract: contracts["mirrorToken"], - msg: { balance: { address: contracts["gov"] } }, - } - - const query = useContractQuery<{ balance: string }>(variables) - return query -} - -/* polls */ -const usePolls = () => { - const { contracts } = useContractsAddress() - - /* contract query */ - const variables = { - contract: contracts["gov"], - msg: { polls: { limit: Math.pow(2, 32) - 1 } }, - } - - const query = useContractQuery(variables) - const { result, parsed } = query - const data = useSelect(parsed) ?? {} - const height = result.data?.[WASMQUERY]?.Height - - /* sort */ - const list = Object.keys(data) - .map(Number) - .sort((a, b) => b - a) - - return { ...query, polls: { data, list, height } } -} - -/* voters */ -export const useVoters = (id: number) => { - const { contracts } = useContractsAddress() - const variables = { - contract: contracts["gov"], - msg: { voters: { poll_id: id, limit: Math.pow(2, 16) - 1 } }, - } - - const { parsed } = useContractQuery<{ voters: Voter[] }>(variables) - return { voters: parsed?.voters } -} - -/* select */ -enum PollType { - WHITELIST = "whitelist", - PARAMETER = "parameter change", -} - -const useSelect = (data?: PollsData) => { - const { getSymbol } = useContractsAddress() - - const parseParams = (decoded: DecodedExecuteMsg, id: number) => { - const type = - "whitelist" in decoded ? PollType.WHITELIST : PollType.PARAMETER - const parsed = - "whitelist" in decoded - ? parseWhitelist(decoded.whitelist) - : "migrate_asset" in decoded - ? parseMigrateAsset(decoded.migrate_asset) - : "update_weight" in decoded - ? parseUpdateWeight(decoded.update_weight) - : parsePassCommand(decoded.pass_command) - - return { type, ...parsed } - } - - const parseWhitelist = ({ params, ...whitelist }: Whitelist) => ({ - msg: whitelist, - params, - }) - - const parseMigrateAsset = (params: MigrateAsset) => { - const { conversion_rate, ...migrate_asset } = params - - return { - msg: migrate_asset, - params: { conversion_rate }, - } - } - - const parseUpdateWeight = ({ asset_token, weight }: UpdateWeight) => ({ - msg: { asset: getSymbol(asset_token) }, - params: { weight }, - }) - - const parsePassCommand = ({ contract_addr, msg }: PassCommand) => { - const decodedPassCommand = fromBase64(msg) - - return "update_asset" in decodedPassCommand - ? parseUpdateAsset(decodedPassCommand.update_asset) - : { - msg: { asset: getSymbol(contract_addr) }, - params: decodedPassCommand.update_config, - } - } - - const parseUpdateAsset = ({ asset_token, ...params }: UpdateAsset) => ({ - msg: { asset: getSymbol(asset_token) }, - params, - }) - - return data?.polls.reduce((acc, poll) => { - try { - const decoded = fromBase64(poll.execute_data.msg) - const parsed = parseParams(decoded, poll.id) - return { ...acc, [poll.id]: { ...poll, ...parsed } } - } catch (error) { - return { ...acc, [poll.id]: poll } - } - }, {}) -} diff --git a/src/graphql/useNormalize.ts b/src/graphql/useNormalize.ts deleted file mode 100644 index 4cc4809e..00000000 --- a/src/graphql/useNormalize.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Dictionary } from "ramda" -import { MIR, UUSD } from "constants/constants" -import { plus, div, floor, gt } from "libs/math" -import calc from "helpers/calc" -import { PriceKey, AssetInfoKey } from "hooks/contractKeys" -import { BalanceKey, AccountInfoKey } from "hooks/contractKeys" -import { useContractsAddress } from "hooks/useContractsAddress" - -export default () => { - const { getListedItem, listed } = useContractsAddress() - - const price = { - [PriceKey.PAIR]: (pairPool: Dictionary) => - dict(pairPool, calcPairPrice), - [PriceKey.ORACLE]: (oraclePrice: Dictionary) => - dict(oraclePrice, ({ price }) => price), - } - - const contractInfo = { - [AssetInfoKey.COMMISSION]: (pairConfig: Dictionary) => - dict(pairConfig, ({ lp_commission, owner_commission }) => - plus(lp_commission, owner_commission) - ), - [AssetInfoKey.LIQUIDITY]: (pairPool: Dictionary) => - dict(pairPool, (pool) => parsePairPool(pool).asset), - [AssetInfoKey.MINCOLLATERALRATIO]: (mintInfo: Dictionary) => - dict(mintInfo, ({ min_collateral_ratio }) => min_collateral_ratio), - [AssetInfoKey.LPTOTALSTAKED]: (stakingPool: Dictionary) => - dict(stakingPool, ({ total_bond_amount }) => total_bond_amount), - [AssetInfoKey.LPTOTALSUPPLY]: (lpTokenInfo: Dictionary) => - dict(lpTokenInfo, ({ total_supply }) => total_supply), - } - - const balance = { - [BalanceKey.TOKEN]: (tokenBalance: Dictionary) => - dict(tokenBalance, ({ balance }) => balance), - [BalanceKey.LPTOTAL]: ( - lpTokenBalance: Dictionary, - stakingReward: StakingReward - ) => reduceLP(listed, { lpTokenBalance, stakingReward }), - [BalanceKey.LPSTAKABLE]: (lpTokenBalance: Dictionary) => - dict(lpTokenBalance, ({ balance }) => balance), - [BalanceKey.LPSTAKED]: (stakingReward: StakingReward) => - reduceBondAmount(stakingReward), - [BalanceKey.MIRGOVSTAKED]: (govStake: Balance) => { - const { token } = getListedItem(MIR) - return { [token]: govStake.balance } - }, - [BalanceKey.REWARD]: ( - stakingPool: Dictionary, - stakingReward: StakingReward - ) => - dict(stakingPool, ({ reward_index: globalIndex }, token) => { - const { reward_infos } = stakingReward - const info = reward_infos?.find((info) => info.asset_token === token) - return floor(calc.reward(globalIndex, info)) - }), - } - - const accountInfo = { - [AccountInfoKey.UUSD]: (bankBalance: BankBalance) => - findBalance(UUSD, bankBalance), - [AccountInfoKey.MINTPOSITIONS]: (mintPosition: MintPositions) => - mintPosition.positions.filter(({ asset }) => gt(asset.amount, 0)), - } - - return { price, contractInfo, balance, accountInfo } -} - -/* utils */ -export const dict = ( - dictionary: Dictionary, - selector: (data: Data, token?: string) => Item -) => - Object.entries(dictionary).reduce>( - (acc, [token, data]) => ({ ...acc, [token]: selector(data, token) }), - {} - ) - -/* helpers */ -const calcPairPrice = (param: PairPool) => { - const { uusd, asset } = parsePairPool(param) - return [uusd, asset].every((v) => v && gt(v, 0)) ? div(uusd, asset) : "0" -} - -export const parsePairPool = ({ assets, total_share }: PairPool) => ({ - uusd: assets.find(({ info }) => "native_token" in info)?.amount ?? "0", - asset: assets.find(({ info }) => "token" in info)?.amount ?? "0", - total: total_share, -}) - -interface LPParams { - lpTokenBalance: Dictionary - stakingReward: StakingReward -} - -const reduceLP = ( - listed: ListedItem[], - { lpTokenBalance, stakingReward }: LPParams -) => - listed.reduce>( - (acc, { token }) => ({ - ...acc, - [token]: plus( - lpTokenBalance[token].balance, - stakingReward.reward_infos.find( - ({ asset_token }) => asset_token === token - )?.bond_amount - ), - }), - {} - ) - -const reduceBondAmount = ({ reward_infos }: StakingReward) => - reward_infos.reduce>( - (acc, { asset_token, bond_amount }) => { - return { ...acc, [asset_token]: bond_amount } - }, - {} - ) - -const findBalance = (denom: string, { BankBalancesAddress }: BankBalance) => - BankBalancesAddress?.Result.find(({ Denom }) => Denom === denom)?.Amount ?? - "0" diff --git a/src/graphql/useTax.ts b/src/graphql/useTax.ts deleted file mode 100644 index cd34c2bc..00000000 --- a/src/graphql/useTax.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useQuery } from "@apollo/client" -import { ceil, min, times } from "../libs/math" -import { TAX } from "./gqldocs" - -export default (amount?: string) => { - const { data } = useQuery(TAX) - return calcTax(amount, data) -} - -/* parse */ -const calcTax = (amount?: string, data?: TaxData) => { - const rate = data?.TreasuryTaxRate.Result - const cap = data?.TreasuryTaxCapDenom.Result - return rate && cap && ceil(min([times(amount, rate), cap])) -} diff --git a/src/graphql/useURL.ts b/src/graphql/useURL.ts deleted file mode 100644 index 42394aec..00000000 --- a/src/graphql/useURL.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { useCallback } from "react" -import { useNetwork } from "../hooks" - -const toQueryMsg = (msg: string) => { - try { - return JSON.stringify(JSON.parse(msg)) - } catch (error) { - return "" - } -} - -export default () => { - const { fcd } = useNetwork() - const getUrl = useCallback( - (contract: string, msg: string | object) => { - const query_msg = - typeof msg === "string" - ? toQueryMsg(msg) - : encodeURIComponent(JSON.stringify(msg)) - return `${fcd}/wasm/contracts/${contract}/store?query_msg=${query_msg}` - }, - [fcd] - ) - return getUrl -} diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts deleted file mode 100644 index c7d5b725..00000000 --- a/src/helpers/parser.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Dictionary } from "ramda" -import { LP, MIR } from "constants/constants" - -const parser: Dictionary> = { - trade: { - Offer: { amountKey: "offer_amount", symbolKey: "offer_asset" }, - Return: { amountKey: "return_amount", symbolKey: "ask_asset" }, - Tax: { amountKey: "tax_amount", symbolKey: "ask_asset" }, - Spread: { amountKey: "spread_amount", symbolKey: "ask_asset" }, - Commission: { amountKey: "commission_amount", symbolKey: "ask_asset" }, - }, - - mint: { - idx: { valueKey: "position_idx" }, - Collateral: { tokenKey: "collateral_amount" }, - Deposit: { tokenKey: "deposit_amount" }, - Withdraw: { tokenKey: "withdraw_amount" }, - Mint: { tokenKey: "mint_amount" }, - Burn: { tokenKey: "burn_amount" }, - Tax: { tokenKey: "tax_amount" }, - }, - - pool: { - Deposit: { tokenKey: "assets" }, - Refund: { tokenKey: "refund_assets" }, - }, - - stake: { Amount: { amountKey: "amount", symbol: LP } }, - claim: { Amount: { amountKey: "amount", symbol: MIR } }, - gov: { id: { valueKey: "poll_id" } }, - - send: { - To: { valueKey: "to" }, - Amount: { amountKey: "amount", symbolKey: "contract_address" }, - }, -} - -export default parser diff --git a/src/helpers/token.ts b/src/helpers/token.ts index d1c9ab1b..0f139063 100644 --- a/src/helpers/token.ts +++ b/src/helpers/token.ts @@ -1,98 +1,20 @@ -import Token from "images/Token/Token.svg" +import DefaultTokenIcon from "images/Token/Token.svg" +import { getSymbol } from "libs/utils" import { tokenInfos } from "rest/usePairs" -import { - AUT, - CAT, - CHT, - CNT, - EUT, - GBT, - HKT, - INT, - JPT, - KRT, - LUNA, - MNT, - SDT, - SGT, - THT, - UAUD, - UCAD, - UCHF, - UCNY, - UEUR, - UGBP, - UHKD, - UINR, - UJPY, - UKRW, - ULUNA, - UMNT, - USDR, - USGD, - UST, - UTHB, - UUSD, -} from "../constants/constants" - -export const getSymbol = (key: string) => { - switch (key) { - case LUNA: - return ULUNA - case KRT: - return UKRW - case SDT: - return USDR - case MNT: - return UMNT - case UST: - return UUSD - case AUT: - return UAUD - case CAT: - return UCAD - case CHT: - return UCHF - case CNT: - return UCNY - case EUT: - return UEUR - case GBT: - return UGBP - case HKT: - return UHKD - case INT: - return UINR - case JPT: - return UJPY - case SGT: - return USGD - case THT: - return UTHB - default: - return "" - } -} - -export const hasTaxToken = (contract_addr: string) => { - if (contract_addr === ULUNA || contract_addr.startsWith("terra")) { - return false - } - - return true -} - -export const GetTokenSvg = (icon: string, symbol: string) => { +export const GetTokenSvg = (icon?: string, symbol?: string) => { if (icon && icon !== "") { return icon } + if (!symbol) { + return "" + } const denom = getSymbol(symbol) - const tokenInfo = tokenInfos.get(denom) + const tokenInfo = tokenInfos.get(denom ?? symbol) if (tokenInfo && tokenInfo.icon !== "") { return tokenInfo.icon } - return Token + return DefaultTokenIcon } diff --git a/src/hooks/forms/useFormData.ts b/src/hooks/forms/useFormData.ts new file mode 100644 index 00000000..cd4feb52 --- /dev/null +++ b/src/hooks/forms/useFormData.ts @@ -0,0 +1,21 @@ +import _ from "lodash" +import { useEffect, useState } from "react" +import { UseFormWatch } from "react-hook-form" + +const useFormData = ( + watch: UseFormWatch, + defaultValues: FormData +) => { + const fd = watch() + const [formData, setFormData] = useState(defaultValues) + + useEffect(() => { + if (!_.isEqual(fd, formData)) { + setFormData(fd) + } + }, [fd, formData]) + + return formData +} + +export default useFormData diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 49669db9..dde34b1e 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,7 +1,3 @@ export { default as useNetwork } from "./useNetwork" export { useConnectModal } from "./useConnectModal" -export { useContractsAddressToken } from "./useContractsAddressToken" -export { useContract, useResult } from "./useContract" export { default as useAddress } from "./useAddress" - -export { default as useCombineResult, useCombineKeys } from "./useCombineResult" diff --git a/src/hooks/useCombineResult.ts b/src/hooks/useCombineResult.ts deleted file mode 100644 index 2f6cc858..00000000 --- a/src/hooks/useCombineResult.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useResult } from "./useContract" -import { DataKey } from "./useContract" - -export const useCombineKeys = (keys: (DataKey | undefined)[]): Result => { - const result = useResult() - const errorKey = keys.find((key) => key && result[key].error) - - return { - data: keys.every((key) => key && result[key].data), - loading: keys.some((key) => key && result[key].loading), - error: errorKey && result[errorKey].error, - } -} - -export default (results: (Result | undefined)[]): Result => { - const findError = (results: (Result | undefined)[]) => { - const errorResult = Object.values(results).find((result) => result?.error) - return errorResult && errorResult.error - } - - return { - data: results.every((result) => result?.data), - loading: results.some((result) => result?.loading), - error: findError(results), - } -} diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts deleted file mode 100644 index 7fc8a2c1..00000000 --- a/src/hooks/useContract.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { LazyQueryResult } from "@apollo/client" -import { Dictionary } from "ramda" - -import { UUSD } from "constants/constants" -import { sum } from "libs/math" - -import usePairPool from "graphql/queries/usePairPool" -import useOraclePrice from "graphql/queries/useOraclePrice" - -import usePairConfig from "graphql/queries/usePairConfig" -import useMintInfo from "graphql/queries/useMintInfo" -import useLpTokenInfo from "graphql/queries/useLpTokenInfo" - -import useBankBalances from "graphql/queries/useBankBalances" -import useMintPositions from "graphql/queries/useMintPositions" - -import useTokenBalance from "graphql/queries/useTokenBalance" -import useLpTokenBalance from "graphql/queries/useLpTokenBalance" -import useStakingReward from "graphql/queries/useStakingReward" -import useStakingPool from "graphql/queries/useStakingPool" -import useGovStake from "graphql/queries/useGovStake" - -import useNormalize from "graphql/useNormalize" - -import createContext from "./createContext" -import { useContractsAddress } from "./useContractsAddress" -import { PriceKey, AssetInfoKey } from "./contractKeys" -import { BalanceKey, AccountInfoKey } from "./contractKeys" - -export type DictionaryKey = PriceKey | BalanceKey | AssetInfoKey -export type DataKey = PriceKey | BalanceKey | AssetInfoKey | AccountInfoKey - -export type QueryResult = LazyQueryResult & { - load: () => void -} - -interface Data extends Record | undefined> { - [AccountInfoKey.UUSD]: string - [AccountInfoKey.MINTPOSITIONS]?: MintPosition[] -} - -interface Helpers { - /** Find the value of the symbol in the data of the given key */ - find: (key: DictionaryKey, symbol: string) => string - /** Sum */ - rewards: string -} - -type Result = Record -type Parsed = Record - -interface Contract extends Data, Helpers { - result: Result - parsed: Parsed -} - -const contract = createContext("useContract") -export const [useContract, ContractProvider] = contract - -/* state */ -export const useContractState = (address: string): Contract => { - const { getListedItem } = useContractsAddress() - - /* price */ - const pairPool = usePairPool() - const oraclePrices = useOraclePrice() - - /* contract info */ - const pairConfig = usePairConfig() - const mintInfo = useMintInfo() - const lpTokenInfo = useLpTokenInfo() - - /* balance */ - const tokenBalance = useTokenBalance(address) - const lpTokenBalance = useLpTokenBalance(address) - const stakingReward = useStakingReward(address) - const govStake = useGovStake(address) - const stakingPool = useStakingPool() - - /* account info */ - const bankBalance = useBankBalances(address) - const mintPositions = useMintPositions(address) - - /* result */ - const result: Result = { - [PriceKey.PAIR]: pairPool.result, - [PriceKey.ORACLE]: oraclePrices.result, - - [AssetInfoKey.COMMISSION]: pairConfig.result, - [AssetInfoKey.LIQUIDITY]: pairPool.result, - [AssetInfoKey.MINCOLLATERALRATIO]: mintInfo.result, - [AssetInfoKey.LPTOTALSTAKED]: stakingPool.result, - [AssetInfoKey.LPTOTALSUPPLY]: lpTokenInfo.result, - - [BalanceKey.TOKEN]: tokenBalance.result, - [BalanceKey.LPTOTAL]: lpTokenBalance.result, // with LPSTAKED - [BalanceKey.LPSTAKABLE]: lpTokenBalance.result, - [BalanceKey.LPSTAKED]: stakingReward.result, - [BalanceKey.MIRGOVSTAKED]: govStake.result, - [BalanceKey.REWARD]: stakingPool.result, // with LPSTAKE - - [AccountInfoKey.UUSD]: bankBalance, - [AccountInfoKey.MINTPOSITIONS]: mintPositions.result, - } - - /* parsed */ - const parsed = { - [PriceKey.PAIR]: pairPool.parsed, - [PriceKey.ORACLE]: oraclePrices.parsed, - - [BalanceKey.TOKEN]: tokenBalance.parsed, - [BalanceKey.LPTOTAL]: lpTokenBalance.parsed, - [BalanceKey.LPSTAKABLE]: lpTokenBalance.parsed, - [BalanceKey.LPSTAKED]: stakingReward.parsed, - [BalanceKey.MIRGOVSTAKED]: govStake.parsed, - [BalanceKey.REWARD]: stakingPool.parsed, - } - - /* Dictionary */ - const { price, contractInfo, balance, accountInfo } = useNormalize() - const dictionary = { - [PriceKey.PAIR]: pairPool.parsed && price[PriceKey.PAIR](pairPool.parsed), - [PriceKey.ORACLE]: - oraclePrices.parsed && price[PriceKey.ORACLE](oraclePrices.parsed), - - [AssetInfoKey.COMMISSION]: - pairConfig.parsed && - contractInfo[AssetInfoKey.COMMISSION](pairConfig.parsed), - [AssetInfoKey.LIQUIDITY]: - pairPool.parsed && contractInfo[AssetInfoKey.LIQUIDITY](pairPool.parsed), - [AssetInfoKey.MINCOLLATERALRATIO]: - mintInfo.parsed && - contractInfo[AssetInfoKey.MINCOLLATERALRATIO](mintInfo.parsed), - [AssetInfoKey.LPTOTALSTAKED]: - stakingPool.parsed && - contractInfo[AssetInfoKey.LPTOTALSTAKED](stakingPool.parsed), - [AssetInfoKey.LPTOTALSUPPLY]: - lpTokenInfo.parsed && - contractInfo[AssetInfoKey.LPTOTALSUPPLY](lpTokenInfo.parsed), - - [BalanceKey.TOKEN]: - tokenBalance.parsed && balance[BalanceKey.TOKEN](tokenBalance.parsed), - [BalanceKey.LPTOTAL]: - lpTokenBalance.parsed && - stakingReward.parsed && - balance[BalanceKey.LPTOTAL](lpTokenBalance.parsed, stakingReward.parsed), - [BalanceKey.LPSTAKABLE]: - lpTokenBalance.parsed && - balance[BalanceKey.LPSTAKABLE](lpTokenBalance.parsed), - [BalanceKey.LPSTAKED]: - stakingReward.parsed && - balance[BalanceKey.LPSTAKED](stakingReward.parsed), - [BalanceKey.MIRGOVSTAKED]: - govStake.parsed && balance[BalanceKey.MIRGOVSTAKED](govStake.parsed), - [BalanceKey.REWARD]: - stakingPool.parsed && - stakingReward.parsed && - balance[BalanceKey.REWARD](stakingPool.parsed, stakingReward.parsed), - } - - const data = { - ...dictionary, - [AccountInfoKey.UUSD]: - bankBalance.data && accountInfo[AccountInfoKey.UUSD](bankBalance.data), - [AccountInfoKey.MINTPOSITIONS]: - mintPositions.parsed && - accountInfo[AccountInfoKey.MINTPOSITIONS](mintPositions.parsed), - } - - /* utils */ - const find: Contract["find"] = (key, value) => { - const { token } = getListedItem(value) - const result = dictionary[key]?.[token] - - const USTPrice = "1" - const isUSTPrice = - value === UUSD && Object.values(PriceKey).includes(key) - - const USTBalance = data[AccountInfoKey.UUSD] - const isUSTBalance = - value === UUSD && Object.values(BalanceKey).includes(key) - - return result ?? (isUSTPrice ? USTPrice : isUSTBalance ? USTBalance : "0") - } - - const rewards = sum(Object.values(dictionary[BalanceKey.REWARD] ?? {})) - return { result, parsed, ...data, find, rewards } -} - -/* -Terra Mantle returns the stringified JSON for the WasmContract query. -Therefore, it is necessary to parse them again and then convert them according to the format. -As a result, `data` value as a GraphQL result cannot be used as it is. -Eventually, GraphQL results are collected and provided as an object called `result`. -Developers should take out `data` according to `result`. -*/ - -export const useResult = () => { - const { result } = useContract() - return result -} diff --git a/src/hooks/useContractsAddress.ts b/src/hooks/useContractsAddress.ts deleted file mode 100644 index 979c0b7e..00000000 --- a/src/hooks/useContractsAddress.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { useEffect, useState } from "react" -import { Dictionary } from "ramda" -import createContext from "./createContext" -import { useNetwork } from "hooks" -import { NATIVE_TOKENS } from "constants/constants" -import { getSymbol } from "helpers/token" - -interface ContractAddressJSON { - /** Contract addresses */ - contracts: Dictionary - /** Token addresses */ - whitelist: Dictionary -} - -interface ContractAddressHelpers { - /** Array of listed item */ - listed: ListedItem[] - /** Find contract address with any key */ - getListedItem: (key?: string) => ListedItem - // getSymbol: (key?: string) => string - getSymbol: (key: string) => string - isNativeToken: (key: string) => boolean - /** Convert structure for chain */ - toAssetInfo: (symbol: string) => AssetInfo | NativeInfo - toToken: (params: Asset) => Token - /** Convert from token of structure for chain */ - parseAssetInfo: (info: AssetInfo | NativeInfo) => string - parseToken: (token: AssetToken | NativeToken) => Asset -} - -export type ContractsAddress = ContractAddressJSON & ContractAddressHelpers -const context = createContext("useContractsAddress") -export const [useContractsAddress, ContractsAddressProvider] = context - -/* state */ -export const useContractsAddressState = (): ContractsAddress | undefined => { - const { contract: url } = useNetwork() - const [data, setData] = useState() - - useEffect(() => { - const load = async () => { - const response = await fetch(url) - const json: ContractAddressJSON = await response.json() - setData(json) - } - - load() - }, [url]) - - const helpers = ({ - whitelist, - }: ContractAddressJSON): ContractAddressHelpers => { - const listed = Object.values(whitelist) - - const getListedItem = (key?: string) => - listed.find((item) => Object.values(item).includes(key)) ?? { - symbol: "", - name: "", - token: "", - pair: "", - lpToken: "", - } - - const isNativeToken = (key: string) => - NATIVE_TOKENS.indexOf(key) > -1 ? true : false - - const toAssetInfo = (key: string) => - NATIVE_TOKENS.indexOf(key) > -1 - ? { native_token: { denom: key } } - : { token: { contract_addr: key } } - - const toToken = ({ amount, symbol }: Asset) => ({ - amount, - info: toAssetInfo(symbol), - }) - - const parseAssetInfo = (info: AssetInfo | NativeInfo) => - "native_token" in info - ? info.native_token.denom - : getSymbol(info.token.contract_addr) - - const parseToken = ({ amount, info }: AssetToken | NativeToken) => ({ - amount, - symbol: parseAssetInfo(info), - }) - - return { - listed, - getListedItem, - isNativeToken, - getSymbol, - toAssetInfo, - toToken, - parseAssetInfo, - parseToken, - } - } - - return data && { ...data, ...helpers(data) } -} diff --git a/src/hooks/useContractsAddressToken.ts b/src/hooks/useContractsAddressToken.ts deleted file mode 100644 index be66dc77..00000000 --- a/src/hooks/useContractsAddressToken.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { useEffect, useState } from "react" -import { Dictionary } from "ramda" -import { UUSD } from "constants/constants" -import createContext from "./createContext" -import { useNetwork } from "hooks" - -interface ContractAddressTokenJSON { - /** Contract addresses */ - contracts: Dictionary - /** Token addresses */ - whitelist: Dictionary -} - -interface ContractAddressTokenHelpers { - /** Array of listed item */ - listed: ListedItem[] - /** Find contract address with any key */ - getListedItem: (key?: string) => ListedItem - getSymbol: (key?: string) => string - /** Convert structure for chain */ - toAssetInfo: (symbol: string) => AssetInfo | NativeInfo - toToken: (params: Asset) => Token - /** Convert from token of structure for chain */ - parseAssetInfo: (info: AssetInfo | NativeInfo) => string - parseToken: (token: AssetToken | NativeToken) => Asset -} - -export type ContractsAddressToken = ContractAddressTokenJSON & - ContractAddressTokenHelpers -const context = createContext("useContractsAddressToken") -export const [useContractsAddressToken, ContractsAddressTokenProvider] = context - -/* state */ -export const useContractsAddressTokenState = (): - | ContractsAddressToken - | undefined => { - const { contract: url } = useNetwork() - const [data, setData] = useState() - - useEffect(() => { - const load = async () => { - const response = await fetch(url) - const json: ContractAddressTokenJSON = await response.json() - setData(json) - } - - load() - }, [url]) - - const helpers = ({ - whitelist, - }: ContractAddressTokenJSON): ContractAddressTokenHelpers => { - const listed = Object.values(whitelist) - - const getListedItem = (key?: string) => - listed.find((item) => Object.values(item).includes(key)) ?? { - symbol: "", - name: "", - token: "", - pair: "", - lpToken: "", - } - - const getSymbol = (key?: string) => - key === UUSD ? key : getListedItem(key).symbol - - const toAssetInfo = (symbol: string) => - symbol === UUSD - ? { native_token: { denom: symbol } } - : { token: { contract_addr: getListedItem(symbol)["token"] } } - - const toToken = ({ amount, symbol }: Asset) => ({ - amount, - info: toAssetInfo(symbol), - }) - - const parseAssetInfo = (info: AssetInfo | NativeInfo) => - "native_token" in info - ? info.native_token.denom - : getSymbol(info.token.contract_addr) - - const parseToken = ({ amount, info }: AssetToken | NativeToken) => ({ - amount, - symbol: parseAssetInfo(info), - }) - - return { - listed, - getListedItem, - getSymbol, - toAssetInfo, - toToken, - parseAssetInfo, - parseToken, - } - } - - return data && { ...data, ...helpers(data) } -} diff --git a/src/hooks/useFee.ts b/src/hooks/useFee.ts new file mode 100644 index 00000000..7d2b7030 --- /dev/null +++ b/src/hooks/useFee.ts @@ -0,0 +1,76 @@ +import { CreateTxOptions, Fee, LCDClient } from "@terra-money/terra.js" +import { useLCDClient } from "@terra-money/wallet-provider" +import { useEffect, useRef, useState } from "react" +import useAddress from "./useAddress" + +export const calculateFee = async ( + lcd: LCDClient, + walletAddress: string, + createTxOptions: CreateTxOptions +) => { + try { + const tx = await lcd.tx.create( + [{ address: walletAddress }], + createTxOptions + ) + return tx?.auth_info?.fee + } catch (error) { + console.log(error) + } + return undefined +} + +const useFee = (createTxOptions?: CreateTxOptions) => { + const terra = useLCDClient() + const walletAddress = useAddress() + + const [fee, setFee] = useState(undefined) + const [isCalculating, setIsCalculating] = useState(false) + + const isCalculated = useRef(false) + const calculatedTxOptions = useRef(undefined) + + useEffect(() => { + let isAborted = false + const fetchFee = async () => { + try { + if (isAborted) { + return + } + if ( + createTxOptions && + calculatedTxOptions.current !== createTxOptions + ) { + const calculatedFee = await calculateFee( + terra, + walletAddress, + createTxOptions + ) + + if (isAborted) { + return + } + setFee(calculatedFee) + } + } catch (error) { + console.log(error) + setFee(undefined) + } + if (isAborted) { + return + } + calculatedTxOptions.current = createTxOptions + setIsCalculating(false) + } + + setIsCalculating(true) + setTimeout(() => fetchFee(), isCalculated.current ? 1250 : 0) + + return () => { + isAborted = true + } + }, [createTxOptions, walletAddress, terra]) + + return { fee, isCalculating, createTxOptions: calculatedTxOptions.current } +} +export default useFee diff --git a/src/hooks/useNetwork.ts b/src/hooks/useNetwork.ts index 07a58f11..12dd4821 100644 --- a/src/hooks/useNetwork.ts +++ b/src/hooks/useNetwork.ts @@ -1,16 +1,17 @@ import { useWallet } from "@terra-money/wallet-provider" import { FINDER } from "constants/constants" -import networks from "constants/networks" +import terraswapNetworks from "constants/networks" const useNetwork = () => { - const { network: extNetwork } = useWallet() + const { network } = useWallet() + const getFinderUrl = (address: string, path: string = "account") => + `${FINDER}/${network.chainID}/${path}/${address}` - const network = networks[extNetwork.name] - - const finder = (address: string, path: string = "account") => - `${FINDER}/${extNetwork.chainID}/${path}/${address}` - - return { ...extNetwork, ...network, finder } + return { + ...network, + ...terraswapNetworks[network.name], + getFinderUrl, + } } export default useNetwork diff --git a/src/hooks/useURL.ts b/src/hooks/useURL.ts new file mode 100644 index 00000000..1a7e9701 --- /dev/null +++ b/src/hooks/useURL.ts @@ -0,0 +1,26 @@ +import { toBase64 } from "forms/formHelpers" +import { useCallback } from "react" +import { useNetwork } from "." + +const toQueryMsg = (msg: string) => { + try { + return JSON.stringify(JSON.parse(msg)) + } catch (error) { + return "" + } +} + +export default () => { + const { lcd } = useNetwork() + const getUrl = useCallback( + (contract: string, msg: string | object, baseUrl?: string) => { + const query_msg = + typeof msg === "string" ? toQueryMsg(msg) : JSON.stringify(msg) + return `${ + baseUrl || lcd + }/cosmwasm/wasm/v1/contract/${contract}/smart/${toBase64(query_msg)}` + }, + [lcd] + ) + return getUrl +} diff --git a/src/images/icon-arrow-left-primary.svg b/src/images/icon-arrow-left-primary.svg new file mode 100644 index 00000000..3ef4e5e6 --- /dev/null +++ b/src/images/icon-arrow-left-primary.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icon-arrow-left.svg b/src/images/icon-arrow-left.svg new file mode 100644 index 00000000..fa592769 --- /dev/null +++ b/src/images/icon-arrow-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/img-background.png b/src/images/img-background.png new file mode 100644 index 00000000..3b6891d4 Binary files /dev/null and b/src/images/img-background.png differ diff --git a/src/index.scss b/src/index.scss index b9a87595..ce05d3f8 100644 --- a/src/index.scss +++ b/src/index.scss @@ -12,8 +12,10 @@ body, font-size: $font-size; position: relative; background-color: $realblue; + background-image: url("images/img-background.png"); + background-size: cover; background-repeat: no-repeat; - background-position: 50% calc(100% + 180px); + background-position: 50% 50%; font-family: $font-family-swap; padding-bottom: $footer-height; background-attachment: fixed; diff --git a/src/index.tsx b/src/index.tsx index e15f69b5..fe488a1a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,10 +2,8 @@ import { StrictMode } from "react" import { createRoot } from "react-dom/client" import { BrowserRouter as Router } from "react-router-dom" import "./index.scss" -import "hooks/useContractsAddress" import ScrollToTop from "./layouts/ScrollToTop" import Network from "./layouts/Network" -import Contract from "./layouts/Contract" import App from "./layouts/App" import WalletConnectProvider from "./layouts/WalletConnectProvider" @@ -13,15 +11,13 @@ const container = document.getElementById("terraswap") const root = createRoot(container!) root.render( - - - - - - - - - - + + + + + + + + ) diff --git a/src/layouts/App.tsx b/src/layouts/App.tsx index bd1e1fde..12d51472 100644 --- a/src/layouts/App.tsx +++ b/src/layouts/App.tsx @@ -1,9 +1,7 @@ import { useEffect, useState } from "react" import routes from "routes" -import { ContractProvider, useContractState } from "hooks/useContract" import { ThemeProvider } from "styled-components" import variables from "styles/_export.module.scss" -import { useAddress } from "hooks" import Header from "./Header" import Footer from "./Footer" import container from "components/Container" @@ -42,10 +40,7 @@ const Container = styled(container)` ` const App = () => { - const address = useAddress() - const contract = useContractState(address) const { isLoading: isPairsLoading } = usePairs() - const [isLoading, setIsLoading] = useState(true) useEffect(() => { @@ -59,20 +54,18 @@ const App = () => { return ( - -
    - {!isLoading && ( -
    - - -
     
    -
    {routes()}
    -
    -
    -
    - )} -