2026-02-27 06:55:41 +00:00
< template >
< div class = "local-swap-widget" >
< template v-if = "!canSwap" >
2026-02-27 10:32:04 +00:00
< p class = "swap-warning" > Connect your wallet to swap ETH for $KRK on the local Uniswap pool . < / p >
2026-02-27 06:55:41 +00:00
< / template >
< template v-else >
2026-03-05 12:03:36 +00:00
< div class = "swap-tabs" >
< button
class = "swap-tab"
: class = "{ active: mode === 'buy' }"
data - testid = "swap-mode-buy"
@ click = "setMode('buy')"
> Buy < / button >
< button
class = "swap-tab"
: class = "{ active: mode === 'sell' }"
data - testid = "swap-mode-sell"
@ click = "setMode('sell')"
> Sell < / button >
2026-02-27 06:55:41 +00:00
< / div >
2026-03-05 12:03:36 +00:00
< template v-if = "mode === 'buy'" >
< div class = "swap-field" >
< label for = "local-swap-amount" class = "swap-label" > ETH to spend < / label >
< input id = "local-swap-amount" data -testid = " swap -amount -input " :value = "swapAmount" @ input = "swapAmount = ($event.target as HTMLInputElement).value" type = "number" min = "0" step = "0.01" class = "swap-input" :disabled = "swapping" / >
< / div >
< button class = "swap-button" data -testid = " swap -buy -button " :disabled = "swapping" @click ="buyKrk" >
{ { swapping ? 'Submitting…' : 'Buy KRK' } }
< / button >
< p class = "swap-hint" > Wraps ETH → WETH , approves the swap router , then trades into $KRK . < / p >
< / template >
< template v-else >
< div class = "swap-field" >
< div class = "swap-label-row" >
< label for = "local-sell-amount" class = "swap-label" > KRK to sell < / label >
< span class = "swap-balance" > Balance : { { formattedKrkBalance } } KRK < / span >
< / div >
< div class = "swap-input-row" >
2026-03-05 12:39:15 +00:00
< input id = "local-sell-amount" data -testid = " swap -sell -amount -input " :value = "sellAmount" @ input = "sellAmount = ($event.target as HTMLInputElement).value" type = "number" min = "0" step = "0.01" class = "swap-input" :disabled = "selling" / >
2026-03-05 12:03:36 +00:00
< button class = "max-button" :disabled = "selling" @click ="setMax" > Max < / button >
< / div >
< / div >
< button class = "swap-button sell-button" data -testid = " swap -sell -button " :disabled = "selling" @click ="sellKrk" >
{ { selling ? ( sellPhase === 'approving' ? 'Approving…' : 'Selling…' ) : 'Sell KRK' } }
< / button >
< p class = "swap-hint" > Approves the swap router , then trades $KRK → WETH . < / p >
< / template >
2026-02-27 06:55:41 +00:00
< / template >
< / div >
< / template >
< script setup lang = "ts" >
2026-03-05 12:03:36 +00:00
import { ref , onMounted , computed } from 'vue' ;
2026-02-28 09:32:02 +00:00
import { useSwapKrk } from '@/composables/useSwapKrk' ;
2026-03-05 12:03:36 +00:00
import { formatUnits } from 'viem' ;
const { swapAmount , swapping , canSwap , buyKrk , sellAmount , selling , sellPhase , krkBalance , loadKrkBalance , sellKrk } = useSwapKrk ( ) ;
const mode = ref < 'buy' | 'sell' > ( 'buy' ) ;
const formattedKrkBalance = computed ( ( ) => {
2026-03-05 12:39:15 +00:00
const s = formatUnits ( krkBalance . value , 18 ) ;
const [ whole , frac = '' ] = s . split ( '.' ) ;
const truncFrac = frac . slice ( 0 , 4 ) . replace ( /0+$/ , '' ) ;
const wholeFormatted = BigInt ( whole ) . toLocaleString ( ) ;
return truncFrac ? ` ${ wholeFormatted } . ${ truncFrac } ` : wholeFormatted ;
2026-03-05 12:03:36 +00:00
} ) ;
function setMode ( m : 'buy' | 'sell' ) {
mode . value = m ;
if ( m === 'sell' ) loadKrkBalance ( ) ;
}
2026-02-27 06:55:41 +00:00
2026-03-05 12:39:15 +00:00
async function setMax ( ) {
await loadKrkBalance ( ) ;
2026-03-05 12:03:36 +00:00
sellAmount . value = formatUnits ( krkBalance . value , 18 ) ;
}
onMounted ( ( ) => {
if ( canSwap . value ) loadKrkBalance ( ) ;
} ) ;
2026-02-27 06:55:41 +00:00
< / script >
< style lang = "sass" scoped >
. local - swap - widget
display : flex
flex - direction : column
gap : 16 px
. swap - warning
margin : 0
color : # FFB347
font - size : 14 px
2026-03-05 12:03:36 +00:00
. swap - tabs
display : flex
gap : 8 px
. swap - tab
flex : 1
padding : 8 px 0
border - radius : 8 px
border : 1 px solid # 3 a3a3a
background : # 111111
color : # a3a3a3
font - size : 14 px
font - weight : 600
cursor : pointer
transition : all 0.2 s
& . active
background : # 1 e3a5f
border - color : # 60 a5fa
color : # ffffff
& : hover : not ( . active )
border - color : # 60 a5fa
color : # ffffff
2026-02-27 06:55:41 +00:00
. swap - label
display : block
font - size : 13 px
color : # a3a3a3
margin - bottom : 6 px
2026-03-05 12:03:36 +00:00
. swap - label - row
display : flex
justify - content : space - between
align - items : baseline
margin - bottom : 6 px
. swap - balance
font - size : 12 px
color : # a3a3a3
2026-02-27 06:55:41 +00:00
. swap - field
display : flex
flex - direction : column
2026-03-05 12:03:36 +00:00
. swap - input - row
display : flex
gap : 8 px
2026-02-27 06:55:41 +00:00
. swap - input
background : # 111111
border : 1 px solid # 3 a3a3a
border - radius : 8 px
color : # ffffff
font - size : 16 px
padding : 12 px 16 px
outline : none
transition : border - color 0.2 s
2026-03-05 12:03:36 +00:00
flex : 1
min - width : 0
2026-02-27 06:55:41 +00:00
& : focus
border - color : # 60 a5fa
& : disabled
opacity : 0.5
cursor : not - allowed
2026-03-05 12:03:36 +00:00
. max - button
padding : 0 16 px
border - radius : 8 px
border : 1 px solid # 3 a3a3a
background : # 1 a1a1a
color : # 60 a5fa
font - size : 13 px
font - weight : 600
cursor : pointer
transition : all 0.2 s
white - space : nowrap
& : hover : not ( : disabled )
border - color : # 60 a5fa
background : # 1 e3a5f
& : disabled
opacity : 0.5
cursor : not - allowed
2026-02-27 06:55:41 +00:00
. swap - button
display : flex
align - items : center
justify - content : center
background : linear - gradient ( 135 deg , # 60 a5fa 0 % , # 3 b82f6 100 % )
color : # ffffff
font - size : 16 px
font - weight : 600
padding : 16 px 32 px
border - radius : 12 px
border : none
cursor : pointer
transition : all 0.3 s ease
box - shadow : 0 4 px 12 px rgba ( 96 , 165 , 250 , 0.3 )
& : hover : not ( : disabled )
transform : translateY ( - 2 px )
box - shadow : 0 6 px 16 px rgba ( 96 , 165 , 250 , 0.4 )
background : linear - gradient ( 135 deg , # 3 b82f6 0 % , # 2563 eb 100 % )
& : disabled
opacity : 0.6
cursor : not - allowed
transform : none
2026-03-05 12:03:36 +00:00
& . sell - button
background : linear - gradient ( 135 deg , # f472b6 0 % , # ec4899 100 % )
box - shadow : 0 4 px 12 px rgba ( 244 , 114 , 182 , 0.3 )
& : hover : not ( : disabled )
box - shadow : 0 6 px 16 px rgba ( 244 , 114 , 182 , 0.4 )
background : linear - gradient ( 135 deg , # ec4899 0 % , # db2777 100 % )
2026-02-27 06:55:41 +00:00
. swap - hint
margin : 0
font - size : 12 px
color : # a3a3a3
< / style >