mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-13 12:33:26 +02:00
feat(earn): show own offer status in local orderbook (#1420)
This commit is contained in:
parent
1535a8148e
commit
c832b80a2f
8 changed files with 426 additions and 15 deletions
|
|
@ -2,6 +2,7 @@ import type React from 'react'
|
|||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import * as JAM from '@/constants/jam'
|
||||
import type { FidelityBondUtxo } from '@/hooks/useQueryUtxos'
|
||||
import { jmSessionStore } from '@/store/jmSessionStore'
|
||||
import type { EarnFormValues } from './EarnForm'
|
||||
|
|
@ -10,6 +11,12 @@ import { EarnPage } from './EarnPage'
|
|||
const mocks = vi.hoisted(() => ({
|
||||
developerMode: false,
|
||||
feeConfigMissing: false,
|
||||
orderbookData: vi.fn<() => unknown>(),
|
||||
orderbookQueryOptions: vi.fn(),
|
||||
orderbookQueryState: {
|
||||
isError: false,
|
||||
isLoading: false,
|
||||
},
|
||||
scrollToTop: vi.fn(),
|
||||
startMaker: vi.fn(),
|
||||
startMutationState: {
|
||||
|
|
@ -76,9 +83,13 @@ vi.mock('@tanstack/react-query', () => ({
|
|||
reset: vi.fn(),
|
||||
}
|
||||
}),
|
||||
useQuery: vi.fn(() => ({
|
||||
refetch: mocks.stopMakerRefetch,
|
||||
})),
|
||||
useQuery: vi.fn((options: { queryKey?: unknown[] }) => {
|
||||
if (options.queryKey?.[0] === 'orderbook') {
|
||||
mocks.orderbookQueryOptions(options)
|
||||
return { ...mocks.orderbookQueryState, data: mocks.orderbookData() }
|
||||
}
|
||||
return { refetch: mocks.stopMakerRefetch }
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
|
|
@ -194,9 +205,24 @@ vi.mock('./MoveToJarDialog', () => ({
|
|||
}))
|
||||
|
||||
vi.mock('./OfferCard', () => ({
|
||||
OfferCard: ({ children, nickname }: { children?: React.ReactNode; nickname?: string }) => (
|
||||
OfferCard: ({
|
||||
children,
|
||||
nickname,
|
||||
orderbookStatus,
|
||||
orderbookOffer,
|
||||
fidelityBond,
|
||||
}: {
|
||||
children?: React.ReactNode
|
||||
nickname?: string
|
||||
orderbookStatus?: string
|
||||
orderbookOffer?: { fidelity_bond_value?: number }
|
||||
fidelityBond?: { amount?: number }
|
||||
}) => (
|
||||
<div>
|
||||
offer-card:{nickname}
|
||||
<span>orderbook-status:{orderbookStatus}</span>
|
||||
<span>bond-value:{orderbookOffer?.fidelity_bond_value}</span>
|
||||
<span>bond-amount:{fidelityBond?.amount}</span>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
|
|
@ -251,6 +277,11 @@ describe('EarnPage', () => {
|
|||
beforeEach(() => {
|
||||
mocks.developerMode = false
|
||||
mocks.feeConfigMissing = false
|
||||
mocks.orderbookData.mockReset()
|
||||
mocks.orderbookData.mockReturnValue(undefined)
|
||||
mocks.orderbookQueryOptions.mockReset()
|
||||
mocks.orderbookQueryState.isError = false
|
||||
mocks.orderbookQueryState.isLoading = false
|
||||
mocks.scrollToTop.mockReset()
|
||||
mocks.startMaker.mockReset()
|
||||
mocks.startMaker.mockResolvedValue({})
|
||||
|
|
@ -342,6 +373,51 @@ describe('EarnPage', () => {
|
|||
expect(mocks.stopMakerRefetch).toHaveBeenCalledWith({ throwOnError: true })
|
||||
})
|
||||
|
||||
it('shows the current offer and fidelity bond from the local orderbook', () => {
|
||||
setSession({
|
||||
maker_running: true,
|
||||
offer_list: [{ oid: 7, cjfee: '250', minsize: '5000', ordertype: 'sw0absoffer' }],
|
||||
})
|
||||
mocks.orderbookData.mockReturnValue({
|
||||
offers: [{ counterparty: 'maker-a', oid: 7, fidelity_bond_value: 42_000 }],
|
||||
fidelitybonds: [
|
||||
{ counterparty: 'maker-a', amount: 50_000, locktime: 1_700_000_000 },
|
||||
{ counterparty: 'maker-a', amount: 100_000, locktime: 1_800_000_000 },
|
||||
],
|
||||
})
|
||||
|
||||
render(<EarnPage walletFileName="wallet.jmdat" />)
|
||||
|
||||
expect(screen.getByText('orderbook-status:visible')).toBeInTheDocument()
|
||||
expect(screen.getByText('bond-value:42000')).toBeInTheDocument()
|
||||
expect(screen.getByText('bond-amount:100000')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('polls until the current offer is visible, then slows down', () => {
|
||||
setSession({
|
||||
maker_running: true,
|
||||
offer_list: [{ oid: 7, cjfee: '250', minsize: '5000', ordertype: 'sw0absoffer' }],
|
||||
})
|
||||
|
||||
render(<EarnPage walletFileName="wallet.jmdat" />)
|
||||
|
||||
const { refetchInterval } = mocks.orderbookQueryOptions.mock.calls[0][0] as {
|
||||
refetchInterval: (query: {
|
||||
state: {
|
||||
data?: { offers: Array<{ counterparty: string; oid: number }> }
|
||||
error?: Error | null
|
||||
}
|
||||
}) => number
|
||||
}
|
||||
const visibleData = { offers: [{ counterparty: 'maker-a', oid: 7 }] }
|
||||
|
||||
expect(refetchInterval({ state: {} })).toBe(JAM.WAIT_FOR_UPDATE_ORDERBOOK_POLLING_INTERVAL)
|
||||
expect(refetchInterval({ state: { data: visibleData } })).toBe(JAM.VISIBLE_ORDERBOOK_POLLING_INTERVAL)
|
||||
expect(refetchInterval({ state: { data: visibleData, error: new Error('offline') } })).toBe(
|
||||
JAM.WAIT_FOR_UPDATE_ORDERBOOK_POLLING_INTERVAL,
|
||||
)
|
||||
})
|
||||
|
||||
it('shows waiting states while maker updates', () => {
|
||||
mocks.startMutationState.isSuccess = true
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { useApiClient } from '@/hooks/useApiClient'
|
|||
import { useFeeConfigValidation } from '@/hooks/useFeeConfigValidation'
|
||||
import type { FidelityBondUtxo } from '@/hooks/useQueryUtxos'
|
||||
import { useRefreshSession } from '@/hooks/useRefreshSession'
|
||||
import * as OrderbookApi from '@/lib/api/orderbook'
|
||||
import { getErrorReason } from '@/lib/errorReason'
|
||||
import * as fb from '@/lib/fidelityBondUtils'
|
||||
import { withQueryDelay } from '@/lib/queryClient'
|
||||
|
|
@ -80,6 +81,40 @@ export const EarnPage = ({ walletFileName }: EarnPageProps) => {
|
|||
const [showFeeConfigDialog, setShowFeeConfigDialog] = useState(false)
|
||||
|
||||
const isCurrentOfferAvailable = jmSession?.offer_list && jmSession.offer_list.length > 0
|
||||
const currentOffer = jmSession?.offer_list?.[0]
|
||||
const isCurrentOrderbookOffer = (offer: OrderbookApi.OrderbookOffer) =>
|
||||
offer.counterparty === jmSession?.nickname && String(offer.oid) === String(currentOffer?.oid)
|
||||
|
||||
const {
|
||||
data: orderbookData,
|
||||
isFetching: orderbookIsFetching,
|
||||
isError: orderbookIsError,
|
||||
} = useQuery({
|
||||
queryKey: ['orderbook'],
|
||||
queryFn: withQueryDelay(OrderbookApi.fetchOrderbook, {
|
||||
// avoid flickering and let user briefly know that something is happening in the background
|
||||
delayBefore: 1_000,
|
||||
}),
|
||||
enabled: makerRunning && !!currentOffer && !!jmSession?.nickname,
|
||||
staleTime: Number.POSITIVE_INFINITY,
|
||||
refetchInterval: (query) =>
|
||||
query.state.error || !query.state.data?.offers.some((offer) => isCurrentOrderbookOffer(offer))
|
||||
? JAM.WAIT_FOR_UPDATE_ORDERBOOK_POLLING_INTERVAL
|
||||
: JAM.VISIBLE_ORDERBOOK_POLLING_INTERVAL,
|
||||
})
|
||||
const currentOrderbookOffer = orderbookData?.offers.find((offer) => isCurrentOrderbookOffer(offer))
|
||||
const currentOrderbookFidelityBond =
|
||||
Number(currentOrderbookOffer?.fidelity_bond_value) > 0
|
||||
? orderbookData?.fidelitybonds?.findLast((bond) => bond.counterparty === jmSession?.nickname)
|
||||
: undefined
|
||||
const orderbookStatus =
|
||||
!jmSession?.nickname || orderbookIsFetching
|
||||
? 'checking'
|
||||
: orderbookIsError
|
||||
? 'error'
|
||||
: currentOrderbookOffer
|
||||
? 'visible'
|
||||
: 'missing'
|
||||
|
||||
const stopMakerQueryOptions = stopmakerOptions({
|
||||
client,
|
||||
|
|
@ -261,6 +296,9 @@ export const EarnPage = ({ walletFileName }: EarnPageProps) => {
|
|||
className="motion-safe:animate-in blur-in"
|
||||
value={jmSession.offer_list[0]}
|
||||
nickname={jmSession.nickname}
|
||||
orderbookStatus={orderbookStatus}
|
||||
orderbookOffer={currentOrderbookOffer}
|
||||
fidelityBond={currentOrderbookFidelityBond}
|
||||
>
|
||||
<Button type="button" onClick={() => void onStop()} className="w-full" size="lg">
|
||||
{isWaitingMakerStop ? (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { SessionResponse } from '@joinmarket-webui/joinmarket-ng-api-ts/jm'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { withRuntimeLocale } from '@/test/withRuntimeLocale'
|
||||
import { OfferCard } from './OfferCard'
|
||||
|
||||
type Offer = NonNullable<SessionResponse['offer_list']>[number]
|
||||
|
|
@ -79,4 +80,41 @@ describe('OfferCard', () => {
|
|||
|
||||
expect(screen.getByTestId('child')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows whether the offer is visible in the local orderbook', () => {
|
||||
const { rerender } = render(<OfferCard value={baseOffer} nickname="JMBot" orderbookStatus="visible" />)
|
||||
|
||||
expect(screen.getByText('earn.current.text_orderbook_visible')).toBeInTheDocument()
|
||||
|
||||
rerender(<OfferCard value={baseOffer} nickname="JMBot" orderbookStatus="missing" />)
|
||||
expect(screen.getByText('earn.current.text_orderbook_missing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows the advertised fidelity bond details', () => {
|
||||
withRuntimeLocale('de-DE', () => {
|
||||
render(
|
||||
<OfferCard
|
||||
value={baseOffer}
|
||||
nickname="JMBot"
|
||||
orderbookStatus="visible"
|
||||
orderbookOffer={{
|
||||
counterparty: 'JMBot',
|
||||
oid: 123,
|
||||
ordertype: 'sw0absoffer',
|
||||
minsize: 10_000,
|
||||
maxsize: 50_000,
|
||||
txfee: 500,
|
||||
cjfee: 1_000,
|
||||
fidelity_bond_value: 42_000,
|
||||
}}
|
||||
fidelityBond={{ counterparty: 'JMBot', amount: 100_000, locktime: 1_800_000_000 }}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('earn.current.text_fidelity_bond')).toBeInTheDocument()
|
||||
expect(screen.getByText('earn.current.text_bond_value: 42.000')).toBeInTheDocument()
|
||||
expect(screen.getByText('100000')).toBeInTheDocument()
|
||||
expect(screen.getByText(/earn\.current\.text_bond_locktime/u)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,11 +1,22 @@
|
|||
import type { PropsWithChildren } from 'react'
|
||||
import type { SessionResponse } from '@joinmarket-webui/joinmarket-ng-api-ts/jm'
|
||||
import type { TFunction } from 'i18next'
|
||||
import { FingerprintIcon, HandCoinsIcon, Maximize2Icon, Minimize2Icon } from 'lucide-react'
|
||||
import {
|
||||
CircleAlertIcon,
|
||||
CircleCheckIcon,
|
||||
FingerprintIcon,
|
||||
HandCoinsIcon,
|
||||
Maximize2Icon,
|
||||
Minimize2Icon,
|
||||
PickaxeIcon,
|
||||
SearchIcon,
|
||||
ShieldCheckIcon,
|
||||
} from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Card, CardContent, CardAction, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import type { OrderbookFidelityBond, OrderbookOffer } from '@/lib/api/orderbook'
|
||||
import { cn, factorToPercentage, isAbsoluteOffer, isRelativeOffer } from '@/lib/utils'
|
||||
import { Balance } from '../ui/jam/Balance'
|
||||
import { Label } from '../ui/label'
|
||||
|
|
@ -36,16 +47,50 @@ interface OfferCardProps {
|
|||
className?: string
|
||||
value: Offer
|
||||
nickname: SessionResponse['nickname']
|
||||
orderbookStatus?: 'checking' | 'visible' | 'missing' | 'error'
|
||||
orderbookOffer?: OrderbookOffer
|
||||
fidelityBond?: OrderbookFidelityBond
|
||||
}
|
||||
|
||||
export function OfferCard({ className, value, nickname, children }: PropsWithChildren<OfferCardProps>) {
|
||||
const orderbookStatusEntry = (value: OfferCardProps['orderbookStatus'], t: TFunction) => {
|
||||
return value === 'visible'
|
||||
? { icon: CircleCheckIcon, text: t('earn.current.text_orderbook_visible'), variant: 'success' as const }
|
||||
: value === 'missing'
|
||||
? { icon: SearchIcon, text: t('earn.current.text_orderbook_missing'), variant: 'warning' as const }
|
||||
: value === 'error'
|
||||
? { icon: CircleAlertIcon, text: t('earn.current.text_orderbook_error'), variant: 'destructive' as const }
|
||||
: value === 'checking'
|
||||
? { icon: SearchIcon, text: t('earn.current.text_orderbook_checking'), variant: 'muted' as const }
|
||||
: undefined
|
||||
}
|
||||
|
||||
export function OfferCard({
|
||||
className,
|
||||
value,
|
||||
nickname,
|
||||
orderbookStatus,
|
||||
orderbookOffer,
|
||||
fidelityBond,
|
||||
children,
|
||||
}: PropsWithChildren<OfferCardProps>) {
|
||||
const { t } = useTranslation()
|
||||
const bondValue = Number(orderbookOffer?.fidelity_bond_value) || 0
|
||||
|
||||
const offerInOrderbookStatus = orderbookStatusEntry(orderbookStatus, t)
|
||||
const bondWarning = bondValue === 0 || orderbookOffer?.fidelity_bond_verification_stale === true
|
||||
|
||||
return (
|
||||
<Card className={cn('transition-all duration-300 hover:-translate-y-[2px] hover:shadow-md', className)}>
|
||||
<CardHeader>
|
||||
<CardTitle>{t('earn.current.text_offer')}</CardTitle>
|
||||
<CardDescription></CardDescription>
|
||||
<CardDescription>
|
||||
{offerInOrderbookStatus && (
|
||||
<Badge className="whitespace-normal" variant={offerInOrderbookStatus.variant}>
|
||||
<offerInOrderbookStatus.icon className="shrink-0" />
|
||||
{offerInOrderbookStatus.text}
|
||||
</Badge>
|
||||
)}
|
||||
</CardDescription>
|
||||
<CardAction>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
|
@ -100,8 +145,9 @@ export function OfferCard({ className, value, nickname, children }: PropsWithChi
|
|||
</div>
|
||||
</div>
|
||||
{!!value?.txfee && (
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex flex-col">
|
||||
<div className="flex min-w-0 items-start gap-4">
|
||||
<PickaxeIcon className="mt-0.5 shrink-0" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<Label className="font-semibold">{t('earn.current.text_txfee')}</Label>
|
||||
<span className="text-muted-foreground text-sm">
|
||||
<Balance valueString={String(value?.txfee || '0')} />
|
||||
|
|
@ -109,6 +155,45 @@ export function OfferCard({ className, value, nickname, children }: PropsWithChi
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{fidelityBond !== undefined && (
|
||||
<div className="flex min-w-0 items-start gap-4 sm:col-span-full">
|
||||
<ShieldCheckIcon
|
||||
className={cn('mt-0.5 shrink-0', {
|
||||
'text-brand-success': bondValue > 0,
|
||||
'text-brand-warning': bondWarning,
|
||||
})}
|
||||
/>
|
||||
<div className="min-w-0 flex-1">
|
||||
<Label
|
||||
className={cn('font-semibold', {
|
||||
'text-brand-success': bondValue > 0,
|
||||
'text-brand-warning': bondWarning,
|
||||
})}
|
||||
>
|
||||
{t('earn.current.text_fidelity_bond')}
|
||||
</Label>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex min-w-0 flex-1 flex-col items-start gap-2 sm:flex-row sm:items-center">
|
||||
<span className={bondValue <= 0 ? 'text-muted-foreground' : undefined}>
|
||||
{t('earn.current.text_bond_value')}: {Math.floor(bondValue).toLocaleString()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-muted-foreground">
|
||||
<Balance valueString={String(fidelityBond.amount)} />
|
||||
<span className="text-muted-foreground">
|
||||
{t('earn.current.text_bond_locktime', {
|
||||
date: new Date(fidelityBond.locktime * 1_000).toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
}),
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">{children}</CardFooter>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -87,6 +87,15 @@ export const WAIT_FOR_UPDATE_SESSION_POLLING_DELAY: Milliseconds = Math.max(
|
|||
1,
|
||||
)
|
||||
|
||||
export const WAIT_FOR_UPDATE_ORDERBOOK_POLLING_INTERVAL: Milliseconds = Math.max(
|
||||
parseAsIntOrDefault(import.meta.env.VITE_JAM_WAIT_FOR_UPDATE_ORDERBOOK_POLLING_INTERVAL, 15_000),
|
||||
1_000,
|
||||
)
|
||||
export const VISIBLE_ORDERBOOK_POLLING_INTERVAL: Milliseconds = Math.max(
|
||||
parseAsIntOrDefault(import.meta.env.VITE_JAM_VISIBLE_ORDERBOOK_POLLING_INTERVAL, 120_000),
|
||||
1_000,
|
||||
)
|
||||
|
||||
export const RUNNING_COINJOIN_POLLING_INTERVAL: Milliseconds = Math.max(
|
||||
parseAsIntOrDefault(import.meta.env.VITE_JAM_RUNNING_COINJOIN_POLLING_INTERVAL, 5_000),
|
||||
1_000,
|
||||
|
|
|
|||
|
|
@ -572,7 +572,14 @@
|
|||
"text_txfee": "Transaction Fee",
|
||||
"text_offer_id": "Offer ID",
|
||||
"text_offer_type_absolute": "absolute",
|
||||
"text_offer_type_relative": "relative"
|
||||
"text_offer_type_relative": "relative",
|
||||
"text_orderbook_checking": "Checking local orderbook...",
|
||||
"text_orderbook_visible": "Visible in local orderbook",
|
||||
"text_orderbook_missing": "Not found in local orderbook yet",
|
||||
"text_orderbook_error": "Could not check local orderbook",
|
||||
"text_fidelity_bond": "Fidelity Bond",
|
||||
"text_bond_value": "Bond value",
|
||||
"text_bond_locktime": "locked until {{date}}"
|
||||
},
|
||||
"report": {
|
||||
"title": "Earnings Report",
|
||||
|
|
|
|||
|
|
@ -5,11 +5,18 @@ export interface OrderbookOffer {
|
|||
counterparty: string
|
||||
oid: number
|
||||
ordertype: OfferType
|
||||
minsize: AmountSats | null | undefined
|
||||
maxsize: AmountSats | null | undefined
|
||||
txfee: number | null | undefined
|
||||
cjfee: number | null | undefined
|
||||
fidelity_bond_value: number | null | undefined
|
||||
minsize?: AmountSats | null
|
||||
maxsize?: AmountSats | null
|
||||
txfee?: number | null
|
||||
cjfee?: number | null
|
||||
fidelity_bond_value?: number | null
|
||||
fidelity_bond_verification_stale?: boolean | null
|
||||
directory_nodes?: string[] | null
|
||||
directly_reachable?: boolean | null
|
||||
// TODO: many more fields, e.g.:
|
||||
// fidelity_bond_value
|
||||
// fidelity_bond_verified
|
||||
// features { neutrino_compat: true, nick_auth: true, peerlist_features: true, … }
|
||||
}
|
||||
|
||||
export interface OrderbookFidelityBond {
|
||||
|
|
|
|||
151
src/stories/jam/OfferCard.stories.tsx
Normal file
151
src/stories/jam/OfferCard.stories.tsx
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react-vite'
|
||||
import { OfferCard } from '@/components/earn/OfferCard'
|
||||
|
||||
const meta: Meta<typeof OfferCard> = {
|
||||
title: 'Jam/OfferCard',
|
||||
component: OfferCard,
|
||||
tags: ['autodocs'],
|
||||
}
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof OfferCard>
|
||||
|
||||
export const Absolute: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0absoffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '21',
|
||||
},
|
||||
nickname: 'TEST7i74jfC9M8MV',
|
||||
},
|
||||
}
|
||||
|
||||
export const Relative: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
},
|
||||
}
|
||||
|
||||
export const Checking: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'checking',
|
||||
},
|
||||
}
|
||||
|
||||
export const Visible: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'visible',
|
||||
},
|
||||
}
|
||||
|
||||
export const Missing: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'missing',
|
||||
},
|
||||
}
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'error',
|
||||
},
|
||||
}
|
||||
|
||||
export const RelativeWithFidelityBondNotYetInLocalOrderbook: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'visible',
|
||||
orderbookOffer: {
|
||||
counterparty: 'TESTCKqXnDjxnFHN',
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
fidelity_bond_value: 0,
|
||||
},
|
||||
fidelityBond: {
|
||||
counterparty: 'TESTCKqXnDjxnFHN',
|
||||
amount: 123_456_789,
|
||||
locktime: 1_000_000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const RelativeWithFidelityBondInLocalOrderbook: Story = {
|
||||
args: {
|
||||
value: {
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
minsize: 90_463,
|
||||
maxsize: 9_008_744_958,
|
||||
txfee: 0,
|
||||
cjfee: '0.000021',
|
||||
},
|
||||
nickname: 'TESTCKqXnDjxnFHN',
|
||||
orderbookStatus: 'visible',
|
||||
orderbookOffer: {
|
||||
counterparty: 'TESTCKqXnDjxnFHN',
|
||||
oid: 0,
|
||||
ordertype: 'sw0reloffer',
|
||||
fidelity_bond_value: 123_456_789.1337,
|
||||
},
|
||||
fidelityBond: {
|
||||
counterparty: 'TESTCKqXnDjxnFHN',
|
||||
amount: 123_456_789,
|
||||
locktime: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue