Merge pull request #1 from input-output-hk/nhenin/initializedSwaps
Initialized swaps View
Initialized swaps View
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
yarn.lock
# local env files
.env*.local
webpack: function (config, options) {
config.experiments = {
asyncWebAssembly: true,
topLevelAwait : true,
};
config.module.rules.push({
test: /\.svg$/,
"@types/react-dom": "18.0.8",
"date-fns": "2.29.3",
"fp-ts": "^2.13.1",
"marlowe-ts-sdk": "0.0.6-beta",
"marlowe-ts-sdk": "0.0.17-beta",
"next": "13.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
import React, { Component, useContext, useEffect, useReducer, useState } from 'react'
import { Container, Dropdown, Icon, Input, Label, Loader, Menu } from 'semantic-ui-react'
import Logo from './marlowe-logo.svg'
import { useContext, useEffect, useState } from 'react'
import * as A from 'fp-ts/Array'
import * as T from 'fp-ts/Task'
import * as O from 'fp-ts/Option'
import { CardanoWallet, WalletContext, useNetwork, useWallet, useWalletList, } from '@meshsdk/react'
import * as TE from 'fp-ts/TaskEither'
import { Image } from 'semantic-ui-react'
import { AssetExtended, BrowserWallet, DataSignature, resolveFingerprint } from '@meshsdk/core'
import { WalletContext, useNetwork, } from '@meshsdk/react'
import { AssetExtended, BrowserWallet, resolveFingerprint } from '@meshsdk/core'
import { constant, pipe } from 'fp-ts/lib/function'
import { HexTransactionWitnessSet, MarloweTxCBORHex } from 'marlowe-ts-sdk/src/runtime/common/textEnvelope'
import { AxiosRestClient } from 'marlowe-ts-sdk/src/runtime/endpoints'
import { addressBech32 } from 'marlowe-ts-sdk/src/runtime/common/address'
import { InitialisePayload } from 'marlowe-ts-sdk/src/runtime/write/command'
import { DecodingError } from 'marlowe-ts-sdk/src/runtime/common/codec'
import { ContractDetails } from 'marlowe-ts-sdk/src/runtime/contract/details'
import {initialise} from 'marlowe-ts-sdk/src/runtime/write/command'
import { GETByRangeResponse } from 'marlowe-ts-sdk/src/runtime/contract/endpoints/collection'
export type WalletBroswerExtension = {
import {cip30SDK} from 'marlowe-ts-sdk/src/runtime/'
import { SwapServices, dappName, runtimeUrl, swapServices } from 'pages/Swaps/service'
export type BroswerExtensionDetails = {
name: string,
icon: string,
version: string
export type Connected = { type: 'connected',
isMainnnet : Boolean
marloweSDK : MarloweSDK,
swapServices : SwapServices,
meshExtensionSDK : MeshExtensionSDK
assetBalances : AssetExtended[],
extensionSelected : WalletBroswerExtension
extensionSelectedDetails : BroswerExtensionDetails
disconnect : () => void
}
export type Connecting = { type: 'connecting' }
export type Disconnected = { type: 'disconnected'
connect: (walletName: string) => Promise<void>
installedExtensions : WalletBroswerExtension []
installedExtensions : BroswerExtensionDetails []
}
const runtimeUrl = 'http://0.0.0.0:33298'
const getExtensionInstance : (extensionName : string) => Promise<WalletInstance> = (extensionName) => {
console.log("extensionName", extensionName )
return window.cardano[extensionName.toLowerCase()].enable()
}
const waitConfirmation : (txHash : string ) => TE.TaskEither<Error,boolean> = (txHash) => TE.of (true)
const signMarloweTx : (extensionName : string) => (cborHex :MarloweTxCBORHex) => TE.TaskEither<Error,HexTransactionWitnessSet> =
(extensionName) => (cborHex) =>
pipe( () => getExtensionInstance (extensionName)
, T.chain((extensionInstance) => () => extensionInstance.signTx (cborHex,false))
, TE.fromTask
)
const initialiseWithExtension :
(runtimeUrl : string)
=> (extensionName : string)
=> (changeAddress : string, usedAddresses : string[],collaterals : string[])
=> (payload : InitialisePayload)
=> TE.TaskEither<Error | DecodingError,ContractDetails> =
(runtimeUrl) => (extensionName) => (changeAddress,usedAddresses,collaterals) => (payload) =>
initialise
(AxiosRestClient(runtimeUrl) )
(waitConfirmation)
(signMarloweTx(extensionName))
({ changeAddress: addressBech32(changeAddress)
, usedAddresses: usedAddresses.length == 0
? O.none
: pipe( usedAddresses
, A.map(addressBech32)
, O.some)
, collateralUTxOs: O.some(collaterals)})
(payload)
export type MarloweSDK =
{ dAppName : string
, fetchInitializeContracts : TE.TaskEither<Error | DecodingError,GETByRangeResponse>
, initialise :
(changeAddress : string, usedAddresses : string[],collaterals : string[])
=> (payload: InitialisePayload)
=> TE.TaskEither<Error | DecodingError, ContractDetails>}
const buildMarloweSDK :
(runtimeUrl : string)
=> (extensionName : string)
=> (dAppName : string)
=> MarloweSDK =
(runtimeUrl) => (extensionName) => (dappName) =>
({ dAppName : dappName
, fetchInitializeContracts : AxiosRestClient(runtimeUrl).contracts.getHeadersByRange (O.none) ([dappName,"initialised"])
, initialise : initialiseWithExtension (runtimeUrl)(extensionName)
})
export const useWalletState : () => WalletState =
() => {
disconnect,
} = useContext(WalletContext);
const dappName = 'swap.L1.dapp.by.marlowe.team'
const isMainnnet = pipe(useNetwork (), a => a == 1 )
const installedExtensions = useInstalledWalletExtensions ()
const assetBalances = useAssetBalance()
const connectOption
= pipe( O.Do
, O.bind ( 'walletSelected' , () => pipe (installedExtensions, A.findFirst(w => w.name == connectedWalletName)))
, O.map (({walletSelected}) => ({ type : 'connected'
, O.bind ( 'extensionSelectedDetails' , () => pipe (installedExtensions, A.findFirst(w => w.name == connectedWalletName)))
, O.map (({extensionSelectedDetails}) => ({ type : 'connected'
, isMainnnet : isMainnnet
, marloweSDK : buildMarloweSDK(runtimeUrl)(connectedWalletName)(dappName)
, swapServices : swapServices(cip30SDK(runtimeUrl)(connectedWalletName))(dappName)
, meshExtensionSDK : connectedWalletInstance
, extensionSelected : walletSelected
, extensionSelectedDetails : extensionSelectedDetails
, assetBalances : assetBalances
, disconnect : disconnect} as WalletState)))
const connecting = constant ({ type: 'connecting' } as WalletState)
};
export const useInstalledWalletExtensions = () => {
const [wallets, setWallets] = useState<WalletBroswerExtension[]>([]);
const [wallets, setWallets] = useState<BroswerExtensionDetails[]>([]);
useEffect(() => {
setWallets(BrowserWallet.getInstalledWallets());
}, []);
return wallets;
}
const POLICY_ID_LENGTH = 56;
const toUTF8 = (hex: string) => Buffer.from(hex, 'hex').toString('utf-8');
type WalletInstance = {
experimental: ExperimentalFeatures;
getBalance(): Promise<string>;
getChangeAddress(): Promise<string>;
getNetworkId(): Promise<number>;
getRewardAddresses(): Promise<string[]>;
getUnusedAddresses(): Promise<string[]>;
getUsedAddresses(): Promise<string[]>;
getUtxos(): Promise<string[] | undefined>;
signData(address: string, payload: string): Promise<DataSignature>;
signTx(tx: string, partialSign: boolean): Promise<string>;
submitTx(tx: string): Promise<string>;
};
type ExperimentalFeatures = {
getCollateral(): Promise<string[] | undefined>;
};
export const ConnectedWallet = ({state}) => {
const connected : Connected = state
const { disconnect, extensionSelected , assetBalances , isMainnnet} = connected;
const { disconnect, extensionSelectedDetails , assetBalances , isMainnnet} = connected;
console.log('state' , state)
const lovelaceBalance =
pipe(assetBalances
const decimalADAs = (lovelaceBalance % 1_000_000)
return lovelaceBalance > 0 ? (
<Dropdown
trigger = {<><span className='small'><Image src={extensionSelected.icon} className="walletIcon" alt=""
trigger = {<><span className='small'><Image src={extensionSelectedDetails.icon} className="walletIcon" alt=""
/>{(adas).toString()}.</span>
<span style={{fontSize: "smaller"}}>{decimalADAs + ' '} </span>
<span style={{fontWeight: 'bold',fontSize: "smaller"}}> {isMainnnet ? ' ₳' : ' t₳' }</span>
</Dropdown>
) : (
<Dropdown
trigger = {<><span className='small'><Image src={extensionSelected.icon} className="walletIcon" alt=""
trigger = {<><span className='small'><Image src={extensionSelectedDetails.icon} className="walletIcon" alt=""
/>0 {isMainnnet ? ' ₳ ' : ' t₳'}</span>
</>}
item
/* eslint-disable react/jsx-key */
import { pipe } from 'fp-ts/lib/function';
import { Connected } from 'pages/Hooks/Wallet';
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import * as A from 'fp-ts/Array'
import { Button, Table } from 'semantic-ui-react'
import { unContractId } from 'marlowe-ts-sdk/src/runtime/contract/id';
import { format } from 'marlowe-ts-sdk/src/adapter/wallet/ada';
import { Token, ada } from 'marlowe-ts-sdk/src/language/core/v1/semantics/contract/common/token';
import { InitializedSwap } from './service';
export const InitializedSwaps = ({state }) => {
export const InitializedSwaps = ({initializedSwaps }) => {
console.log("initializedSwaps",initializedSwaps)
return (<Table compact celled striped>
<Table.Header>
<Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>Djed Liquidity for DApp X</Table.Cell>
<Table.Cell>addr_test1qqe34....87eq0td9ja</Table.Cell>
<Table.Cell>100 Token B</Table.Cell>
<Table.Cell>15 Token A</Table.Cell>
<Table.Cell>11 day, 1h, 25 mins</Table.Cell>
<Table.Cell collapsing>
<Button.Group>
<Button>Cancel</Button>
<Button.Or />
<Button positive>Provision</Button>
</Button.Group>
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>Djed Liquidity for DApp X</Table.Cell>
<Table.Cell>addr_test1qqe34....87eq0td9ja</Table.Cell>
<Table.Cell>100 Djeds </Table.Cell>
<Table.Cell>25 ₳</Table.Cell>
<Table.Cell>11 day, 1h, 25 mins</Table.Cell>
<Table.Cell collapsing>
<Button.Group>
<Button>Cancel</Button>
<Button.Or />
<Button positive>Provision</Button>
</Button.Group>
</Table.Cell>
</Table.Row>
{(initializedSwaps as InitializedSwap[]).map(initializedSwap =>
(<Table.Row key={unContractId(initializedSwap.contractId)}>
<Table.Cell>{initializedSwap.swap.note}</Table.Cell>
<Table.Cell>addr_test1qqe34....87eq0td9ja</Table.Cell>
<Table.Cell>{displayToken ( initializedSwap.swap.b.amount ,initializedSwap.swap.b.token) }</Table.Cell>
<Table.Cell>{displayToken ( initializedSwap.swap.self.amount, initializedSwap.swap.self.token)}</Table.Cell>
<Table.Cell>11 day, 1h, 25 mins</Table.Cell>
<Table.Cell collapsing>
<Button.Group>
<Button>Cancel</Button>
<Button.Or />
<Button positive>Provision</Button>
</Button.Group>
</Table.Cell>
</Table.Row>)
)}
</Table.Body>
</Table>)
}
const displayToken = (amount:bigint, token: Token) : string => {
if (token.currency_symbol === "lovelace") return format(amount).valueOf()
else { return amount + ' ' + token.token_name }
}
import { pipe } from 'fp-ts/lib/function'
import React, { useState } from 'react'
import { Icon, Message } from 'semantic-ui-react'
import { Message } from 'semantic-ui-react'
import { addDays } from 'date-fns/fp'
import {format} from 'date-fns'
import {
} from 'semantic-ui-react'
import { Connected } from '../Hooks/Wallet'
import * as A from 'fp-ts/Array'
import * as T from 'fp-ts/Task'
import * as TE from 'fp-ts/TaskEither'
import * as O from 'fp-ts/Option'
import { AssetExtended, BrowserWallet, Unit } from '@meshsdk/core'
import { AssetExtended } from '@meshsdk/core'
import * as Swaps from 'marlowe-ts-sdk/src/language/core/v1/examples/swaps/swap-token-token'
import { datetoTimeout } from 'marlowe-ts-sdk/src/language/core/v1/semantics/contract/when'
import { token } from 'marlowe-ts-sdk/src/language/core/v1/semantics/contract/common/token'
import { addressBech32 } from 'marlowe-ts-sdk/src/runtime/common/address'
import { MarloweJSONCodec } from 'marlowe-ts-sdk/src/adapter/json'
export const NewSwap = ({state }) => {
const submit = async (event) => {
event.preventDefault();
const {marloweSDK,meshExtensionSDK} = connectedWallet
const usedAddresses = await meshExtensionSDK.getUsedAddresses ()
const collaterals = await meshExtensionSDK.getCollateral()
const changeAddress = await meshExtensionSDK.getChangeAddress ()
const swapRequest = { tokenA_DepositTimeout : pipe(Date.now(),addDays(1),datetoTimeout)
, tokenB_DepositTimeout : pipe(Date.now(),addDays(2),datetoTimeout)
, tokenA : token(asset.policyId,asset.assetName)
, tokenA_Amount : amount
, tokenB : token(policyIdToSwap,tokenNameToSwap)
, tokenB_Amount : amountToSwap }
const swap = Swaps.swap_tokenA_tokenB(swapRequest)
const {swapServices} = connectedWallet
await pipe
( marloweSDK.initialise
(changeAddress,usedAddresses,collaterals)
({ contract: swap
, roles: {'Ada provider' : addressBech32(changeAddress)
,'Token provider' : addressBech32(recipient)}
, version: 'v1'
, metadata: {}
, tags : {'swap.L1.dapp.by.marlowe.team' : { 'note' : note }
,"initialised" : {}}
, minUTxODeposit: 3_000_000})
, TE.chainFirst ( () => marloweSDK.fetchInitializeContracts)
( swapServices.initialize
(addressBech32 (recipient) )
({ note : note
, self : { depositTimeout : pipe(Date.now(),addDays(1),datetoTimeout)
, token : token(asset.policyId,asset.assetName)
, amount : amount }
, b : { depositTimeout : pipe(Date.now(),addDays(2),datetoTimeout)
, token : token(policyIdToSwap,tokenNameToSwap)
, amount : amountToSwap }})
, TE.match (
(error) => { console.log(error)
setSubmitFailed(JSON.stringify(error))
setSubmitSucceed('')},
(initializeContracts) =>
{ console.log(initializeContracts)
setSubmitSucceed(MarloweJSONCodec.encode(initializeContracts))
() =>
{
setSubmitSucceed('Successfully created your swap')
setSubmitFailed('') })
)()
};
import { useContext, useEffect, useState } from 'react'
import * as A from 'fp-ts/Array'
import * as O from 'fp-ts/Option'
import { WalletContext, useNetwork, } from '@meshsdk/react'
import * as TE from 'fp-ts/TaskEither'
import { AssetExtended, BrowserWallet, resolveFingerprint } from '@meshsdk/core'
import { constVoid, constant, pipe } from 'fp-ts/lib/function'
import { AddressBech32, addressBech32 } from 'marlowe-ts-sdk/src/runtime/common/address'
import { DecodingError } from 'marlowe-ts-sdk/src/runtime/common/codec'
import {SDK, cip30SDK} from 'marlowe-ts-sdk/src/runtime/'
import { GETByRangeResponse } from 'marlowe-ts-sdk/src/runtime/contract/endpoints/collection'
import * as Swaps from 'marlowe-ts-sdk/src/language/core/v1/examples/swaps/swap-token-token'
import { Timeout } from 'marlowe-ts-sdk/src/language/core/v1/semantics/contract/when'
import { Token } from 'marlowe-ts-sdk/src/language/core/v1/semantics/contract/common/token'
import { ContractId } from 'marlowe-ts-sdk/src/runtime/contract/id'
export const runtimeUrl = 'http://0.0.0.0:40124'
export const dappName = 'dApp.swap.L1'
export type SwapState = 'initialised' | 'provisionned' | 'requested' | 'done'
export type SwapContext
= { note : string
, self : { depositTimeout : Timeout
, token:Token
, amount:bigint}
, b : { depositTimeout : Timeout
, token:Token
, amount:bigint} }
export type InitializedSwap = {contractId : ContractId, swap : SwapContext }
export type ProvisionnedSwap = {contractId : ContractId, swap : SwapContext }
export type RequestedSwap = {contractId : ContractId, swap : SwapContext }
export type ClosedSwap = {contractId : ContractId, swap : SwapContext }
export type SwapServices =
{ dAppName : string
, mySwaps : { initializedSwaps : TE.TaskEither<Error | DecodingError,InitializedSwap[]> }
, initialize : (recipient : AddressBech32) => (context :SwapContext) => TE.TaskEither<Error | DecodingError,void> }
export const swapServices :
(sdk : SDK)
=> (dAppName : string)
=> SwapServices =
(sdk) => (dappName) =>
({ dAppName : dappName
, mySwaps : { initializedSwaps :
pipe (sdk.restAPI.contracts.getHeadersByRange (O.none) ([dappName + '.initialised'])
, TE.map (data => pipe (data.headers,
A.map (header => ({ contractId : header.contractId
, swap : header.tags["context"] as SwapContext })) ) )) }
, initialize : (recipient) => (swapContext) =>
pipe( sdk.wallet.getChangeAddress
, TE.fromTask
, TE.chain ( changeAddress =>
sdk.commands.initialise
({ contract: Swaps.swap_tokenA_tokenB({ a : { roleName : "Swap Request Handler"
, depositTimeout : swapContext.self.depositTimeout
, token : swapContext.self.token
, amount : swapContext.self.amount }
, b : { roleName : "Swap Exchange Handler"
, depositTimeout :swapContext.b.depositTimeout
, token : swapContext.b.token
, amount : swapContext.b.amount }})
, roles: { ["Swap Request Handler"] : changeAddress
, ["Swap Exchange Handler"] : recipient}
, version: 'v1'
, metadata: {}
, tags : { [dappName + '.initialised'] : { }
, context : swapContext }
, minUTxODeposit: 3_000_000}))
, TE.map (constVoid))
})
import React, { Component, useContext, useEffect, useReducer, useState } from 'react'
import React, { Component, useCallback, useContext, useEffect, useReducer, useState } from 'react'
import { Container, Dropdown, Icon, Input, Label, Loader, Menu } from 'semantic-ui-react'
import Logo from './marlowe-logo.svg'
import * as A from 'fp-ts/Array'
import * as T from 'fp-ts/Task'
import * as O from 'fp-ts/Option'
import * as E from 'fp-ts/Either'
import { CardanoWallet, WalletContext, useLovelace, useNetwork, useWallet, useWalletList, } from '@meshsdk/react'
import * as TE from 'fp-ts/TaskEither'
import { Button, Checkbox, Table } from 'semantic-ui-react'
import { Segment, Tab } from 'semantic-ui-react'
import { ProvisionnedSwaps } from './provisionned'
import { NewSwap } from './new'
import { RequestedSwaps } from './requested'
import { Connected, WalletState, useWalletState } from '../Hooks/Wallet'
import { useWalletState } from '../Hooks/Wallet'
import { InitializedSwaps } from './initialized'
import { pipe } from 'fp-ts/lib/function'
import { ClosedSwaps } from './closed'
import { InitializedSwap, RequestedSwap, ProvisionnedSwap, ClosedSwap, SwapServices } from './service'
const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
const panes = (walletState : WalletState) =>
{switch (walletState.type) {
case 'disconnected' : return [{
menuItem: <Menu.Item key='About'>About</Menu.Item>,
render: () => <p> {loremIpsum}</p>,}]
case 'connecting' : return [{
menuItem: <Menu.Item key='About'>About</Menu.Item>,
render: () => <p> {loremIpsum}</p>,}]
case 'connected' :
return [
{
menuItem: <Menu.Item key='About'>About</Menu.Item>,
render: () => <p> {loremIpsum}</p>},
{
menuItem: <Menu.Item key='requested'>Requests<Label>2</Label></Menu.Item>,
render: () => <RequestedSwaps/>,
},
{
menuItem: <Menu.Item key='new'><Icon name='add circle' color='grey' size='large' /> New </Menu.Item>,
render: () => <NewSwap state={walletState}/>,
},
{
menuItem: <Menu.Item key='initialized'>Initialized<Label>1</Label></Menu.Item>,
render: () => <InitializedSwaps/>,
},
{
menuItem: <Menu.Item key='provisionned'>Provisionned<Label>2</Label></Menu.Item>,
render: () => <ProvisionnedSwaps/>,
},
{
menuItem: <Menu.Item key='closed'>Done<Label>3</Label></Menu.Item>,
render: () => <RequestedSwaps />,
},
]}}
const fetchInitializedSwaps = (swapServices : SwapServices ) =>
{console.log("here")
const noInitializedSwap : InitializedSwap[] = []
return pipe( swapServices.mySwaps.initializedSwaps
, TE.fold( a => T.of(noInitializedSwap),a => T.of(a))) ()
}
export const SwapTabs = () => {
const walletState = useWalletState();
console.log("there", walletState)
return (<div>
<Tab panes={panes(walletState)} />
</div>)
let walletState = useWalletState();
let [requestedSwaps, setRequestedSwap] = useState<RequestedSwap[]>([]);
let [initializedSwaps, setInitializedSwaps] = useState<InitializedSwap[]>([]);
let [provisionnedSwaps, setProvisionnedSwap] = useState<ProvisionnedSwap[]>([]);
let [closedSwaps, setClosedSwap] = useState<ClosedSwap[]>([]);
console.log(initializedSwaps)
const panes = () => { switch (walletState.type) {
case 'disconnected' : return panesDisconnected
case 'connecting' : return panesConnecting
case 'connected' :
return [
{ menuItem: <Menu.Item key='About'>About</Menu.Item>, render: () => <p> {loremIpsum}</p>},
menuRequestedSwaps(requestedSwaps),
{ menuItem: <Menu.Item key='new'><Icon name='add circle' color='grey' size='large' /> New </Menu.Item>,
render: () => <NewSwap state={walletState}/>},
menuInitializedSwaps(initializedSwaps),
menuProvisionnedSwaps(provisionnedSwaps),
menuClosedSwaps (closedSwaps)
]
}}
useEffect(() => {
if(walletState.type == 'connected') {
fetchInitializedSwaps(walletState.swapServices)
.then (setInitializedSwaps)
}
}
, [walletState.type,initializedSwaps.length]);
return (<div><Tab panes={panes()} /></div>)
}
const menuInitializedSwaps = (initializedSwaps:InitializedSwap[]) => (initializedSwaps.length === 0 ) ? {} :
({ menuItem: <Menu.Item key='initialized'>Initialized<Label>{initializedSwaps.length}</Label></Menu.Item>,
render: () => <InitializedSwaps initializedSwaps={initializedSwaps}/>,
})
const menuProvisionnedSwaps = (provisionnedSwaps) => (provisionnedSwaps.length === 0 ) ? {} :
({ menuItem: <Menu.Item key='provisionned'>Provisionned<Label>{provisionnedSwaps.length}</Label></Menu.Item>,
render: () => <ProvisionnedSwaps />,
})
const menuClosedSwaps = (closedSwaps) => (closedSwaps.length === 0 ) ? {} :
({ menuItem: <Menu.Item key='closed'>Closed<Label>{closedSwaps.length}</Label></Menu.Item>,
render: () => <ClosedSwaps />,
})
const menuRequestedSwaps = (closedSwaps) => (closedSwaps.length === 0 ) ? {} :
({ menuItem: <Menu.Item key='requested'>Requested<Label>{closedSwaps.length}</Label></Menu.Item>,
render: () => <RequestedSwaps />,
})
const panesDisconnected = [{
menuItem: <Menu.Item key='About'>About</Menu.Item>,
render: () => <p> <br/> {loremIpsum}</p>,}]
const panesConnecting = [{
menuItem: <Menu.Item key='About'>About</Menu.Item>,
render: () => <p> <br/> {loremIpsum}</p>,}]
const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
Added ToExpr instances Moved ImpTest to cardano-ledger-conway:testlib Moved ConwayEpochs to cardano-ledger-conway:test
## Issue ADP-3157 ## Summary This PR replaces the use of `Cardano.Wallet.Primitive.Types.Coin` with `Cardano.Ledger.Coin` in the type signature of `balanceTransaction`.