Skip to content

Commit

Permalink
PUBLIC: Add token filter feature based on available user balance to a…
Browse files Browse the repository at this point in the history
…void error while pay. If checkout price as token is above user owned balance for specified token, payment is unavailable
  • Loading branch information
devsbequest committed Nov 21, 2023
1 parent fc9e14b commit 8d43af8
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 11 deletions.
102 changes: 93 additions & 9 deletions assets/js/commons/components/dialogs/content/PayTokenSelector.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script lang="ts">
import {truncateToPrecision} from '../../../utils/price'
import {getUserBalanceForToken} from '../../../utils/tokens'
import {getConvertedToUSD} from '../../../services/PriceRate'
import {onMount} from 'svelte';
import type { TokenRate } from '../../../type';
import { getTokensPrices } from '../../../services/TokensPrices';
import {getUserBalances} from '../../../services/UserBalance'
import Processing from '../../processing/Processing.svelte';
export let allowedTokens:string;
Expand All @@ -27,22 +29,56 @@
const allowedTokensArray = allowedTokens.split(',');
let allowedTokenRates:TokenRate[] = [];
let refreshing = true
onMount(async ()=>{
refresh();
})
async function refresh (){
refreshing = true
const userBalances = await getUserBalances(actorName,false);
console.log(userBalances)
const convertedOrderAmountAsUsd = await getConvertedToUSD(baseDomain,storeCurrency,parseFloat(cartAmount));
if (convertedOrderAmountAsUsd.status == 200){
usdCartAmount = convertedOrderAmountAsUsd.data.body_response
}
const tokenRatesResult = await getTokensPrices(baseDomain);
if (tokenRatesResult.status == 200){
allowedTokenRates = tokenRatesResult.data.body_response.reduce((prev:TokenRate[],current)=>{
allowedTokenRates = tokenRatesResult.data.body_response.reduce((prev:TokenRate[],current:TokenRate):TokenRate[]=>{
if(allowedTokensArray.some((token)=>token == current.symbol)){
prev.push(current);
}
return prev;
},[]);
},[])
allowedTokenRates = allowedTokenRates.map((tokenRate)=>{
const rate = {...tokenRate}
const availableUserBalance = getUserBalanceForToken(rate.pair_base,userBalances)
if (availableUserBalance){
rate.availableUserBalance = parseFloat(availableUserBalance.amount)
rate.enable = parseFloat(availableUserBalance.amount)>=convertFiatPriceToToken(usdCartAmount,rate.pair_base)
console.log(tokenRate.pair_base,usdCartAmount,parseFloat(availableUserBalance.amount),convertFiatPriceToToken(usdCartAmount,rate.pair_base))
}else {
rate.enable = false;
rate.availableUserBalance = 0
}
return rate;
})
allowedTokenRates = allowedTokenRates.sort(orderTokensRate);
refreshing = false
}
})
}
function convertFiatPriceToToken (fiatAmount:number,symbol:string){
const rate = getTokenRateBySymbol(symbol)
Expand All @@ -56,25 +92,43 @@
return allowedTokenRates.find((token)=>token.symbol == symbol);
}
function orderTokensRate (a:TokenRate,b:TokenRate) {
console.log('order',a,b)
return +b.enable - +a.enable
}
</script>


{#if usdCartAmount}
<span><b>{cartAmount} {storeCurrency} = {truncateToPrecision(usdCartAmount,2)} USD</b></span>
<div class="usd_cart_amount">
<span><b>{cartAmount} {storeCurrency} = {truncateToPrecision(usdCartAmount,2)} USD</b></span>
<a on:click={()=>refresh()}>Refresh </a>
</div>
{/if}
{#if allowedTokenRates.length == 0}
{#if refreshing}
<Processing label={translations.processingLabel}></Processing>
{:else}
<div style="overflow-y:auto; max-height:100%">
<ul class="token_rates__list">
{#each allowedTokenRates as token }
<li >
<a aria-roledescription="Select token" class="woow-button button token_rates__list__render_item " on:click={()=>selectPayToken(getTokenRateBySymbol(token.symbol),convertFiatPriceToToken(usdCartAmount,token.symbol))}>
<a aria-roledescription="Select token" class={`${token.enable ? '' : 'disabled'} woow-button button token_rates__list__render_item`} on:click={()=>selectPayToken(getTokenRateBySymbol(token.symbol),convertFiatPriceToToken(usdCartAmount,token.symbol))}>
<img src={token.logo} />
<h5 class="token_rates__list__render_item__token_price">
{translations.payLabel} {convertFiatPriceToToken(usdCartAmount,token.symbol)} {token.symbol}
</h5>
<div>
<h5 class="token_rates__list__render_item__token_price">
{translations.payLabel} {convertFiatPriceToToken(usdCartAmount,token.symbol)} {token.symbol}
</h5>
<p class="token_rates__list__render_item__token_balance">
Balance
{token.availableUserBalance}
{token.symbol}
</p>
</div>

<div class="token_rates__list__render_item__drill_icon">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
</div>
Expand All @@ -89,6 +143,13 @@

<style>
.usd_cart_amount {
display: flex;
justify-content: space-between;
}
.token_rates{
display: grid;
Expand Down Expand Up @@ -118,6 +179,19 @@
gap:10px;
}
.token_rates__list__render_item.disabled {
pointer-events: none;
opacity: 0.3;
}
.token_rates__list__render_item.disabled .token_rates__list__render_item__drill_icon {
display: none;
}
.token_rates__list__render_item__drill_icon {
Expand All @@ -136,4 +210,14 @@
text-transform: none;
}
.token_rates__list__render_item__token_balance {
text-align: left;
font-size: 12px;
padding: 0;
margin: 0;
text-transform: none;
text-decoration: none!important;
}
</style>
14 changes: 14 additions & 0 deletions assets/js/commons/services/UserBalance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MAINNET_ENDPOINTS, TESTNET_ENDPOINTS } from '../../commons/constants/endpoints';
import { JsonRpc } from "@proton/light-api"
import type { UserBalance } from '../type';


export async function getUserBalances(actor: string, isTestnet: boolean):Promise<UserBalance[]> {

const rpc = new JsonRpc("proton")
const userBalance = await rpc.get_balances(actor);
if (userBalance && userBalance.balances) return userBalance.balances;
return []


}
14 changes: 12 additions & 2 deletions assets/js/commons/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@ export interface TokenRate{
id: string
logo?: string;
quote: {
price_usd:number
}
price_usd: number
};
availableUserBalance: number;
enable: boolean;
pair_base: string;
}

export interface UserBalance {
currency: string
contract: string
decimals: string
amount: string
}


Expand Down
10 changes: 10 additions & 0 deletions assets/js/commons/utils/tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {UserBalance } from "../type";

export function getUserBalanceForToken(token:string,userBalances:UserBalance[]) {

const foundToken = userBalances.find((balance) => balance.currency == token)
if (foundToken) return foundToken
return null


}

0 comments on commit 8d43af8

Please sign in to comment.