diff --git a/api/src/features/transfers/transfers.service.ts b/api/src/features/transfers/transfers.service.ts index 01ff3620f..0a9457b03 100644 --- a/api/src/features/transfers/transfers.service.ts +++ b/api/src/features/transfers/transfers.service.ts @@ -8,8 +8,7 @@ import { selectAccount } from '../accounts/accounts.util'; import { uuid } from 'edgedb/dist/codecs/ifaces'; import { Shape } from '../database/database.select'; import { PricesService } from '../prices/prices.service'; -import { Address, BigIntlike } from 'lib'; -import { formatUnits } from 'viem'; +import { Address, tokenToFiat } from 'lib'; export const TRANSFER_VALUE_FIELDS_SHAPE = { token: { @@ -23,19 +22,6 @@ export const TRANSFER_VALUE_FIELDS_SHAPE = { const s = e.select(e.TransferDetails, () => TRANSFER_VALUE_FIELDS_SHAPE); export type TransferValueSelectFields = $infer[0]; -const FIAT_DECIMALS = 8; -const fiatAsBigInt = (value: number): bigint => BigInt(Math.floor(value * 10 ** FIAT_DECIMALS)); - -export interface TokenValueOptions { - amount: BigIntlike; - decimals: number; - price: number; -} - -export function getTokenValue({ amount, decimals, price }: TokenValueOptions): number { - return parseFloat(formatUnits(BigInt(amount) * fiatAsBigInt(price), decimals + FIAT_DECIMALS)); -} - @Injectable() export class TransfersService { constructor(private db: DatabaseService, private prices: PricesService) {} @@ -76,7 +62,7 @@ export class TransfersService { ); if (!p) return null; - const value = getTokenValue({ amount, decimals: token.decimals, price: p.current }); + const value = tokenToFiat(amount, p.current, token.decimals); return direction === 'In' ? value : -value; } diff --git a/app/src/components/InputsView.tsx b/app/src/components/InputsView.tsx index a5ffe8d20..57a7f6b1b 100644 --- a/app/src/components/InputsView.tsx +++ b/app/src/components/InputsView.tsx @@ -1,14 +1,13 @@ import { FragmentType, gql, useFragment } from '@api/gen'; import { SwapVerticalIcon } from '@theme/icons'; import { makeStyles } from '@theme/makeStyles'; -import { fiatAsBigInt, tokenToFiat, valueAsTokenAmount } from '@token/fiat'; import { formatUnits, parseUnits } from 'ethers/lib/utils'; -import { asBigInt } from 'lib'; +import { asBigInt, fiatToToken, tokenToFiat } from 'lib'; import { Dispatch, SetStateAction } from 'react'; import { View } from 'react-native'; import { Button, IconButton, Text } from 'react-native-paper'; import { FiatValue } from '~/components/fiat/FiatValue'; -import { TokenAmount } from '~/components/token/TokenAmount2'; +import { TokenAmount } from '~/components/token/TokenAmount'; import { logWarning } from '~/util/analytics'; const FragmentDoc = gql(/* GraphQL */ ` @@ -52,12 +51,12 @@ export const InputsView = ({ input, setInput, type, setType, ...props }: InputsV const tokenAmount = type === InputType.Token ? parseUnits(inputAmount, token.decimals).toBigInt() - : valueAsTokenAmount(parseFloat(inputAmount), token.price?.current ?? 0, token.decimals); + : fiatToToken(parseFloat(inputAmount), token.price?.current ?? 0, token.decimals); const fiatValue = type === InputType.Token - ? tokenToFiat(tokenAmount, asBigInt(token.price?.current) ?? 0n, token.decimals) - : fiatAsBigInt(inputAmount); + ? tokenToFiat(tokenAmount, token.price?.current ?? 0, token.decimals) + : parseFloat(inputAmount); return ( diff --git a/app/src/components/fiat/FiatValue.tsx b/app/src/components/fiat/FiatValue.tsx index 9fd511ea0..ce03836b6 100644 --- a/app/src/components/fiat/FiatValue.tsx +++ b/app/src/components/fiat/FiatValue.tsx @@ -1,4 +1,4 @@ -import { FIAT_DECIMALS } from '~/util/token/fiat'; +import { FIAT_DECIMALS } from 'lib'; import { FormattedNumberOptions, useFormattedNumber } from '../format/FormattedNumber'; const currency = 'USD'; diff --git a/app/src/components/token/TokenItem.tsx b/app/src/components/token/TokenItem.tsx index 349db69be..f75f9fdb7 100644 --- a/app/src/components/token/TokenItem.tsx +++ b/app/src/components/token/TokenItem.tsx @@ -4,7 +4,7 @@ import { ListItem, ListItemProps } from '../list/ListItem'; import { ListItemSkeleton } from '../list/ListItemSkeleton'; import { withSuspense } from '../skeleton/withSuspense'; import { TokenAmount } from './TokenAmount'; -import { BigIntlike, getTokenValue } from 'lib'; +import { BigIntlike, tokenToFiat } from 'lib'; import { FragmentType, gql, useFragment } from '@api/gen'; import { TokenIcon } from './TokenIcon/TokenIcon'; @@ -54,13 +54,7 @@ export const TokenItem = withSuspense( trailing={({ Text }) => token.price && ( - + ) } diff --git a/app/src/screens/contract-permissions/ContractPermissionsScreen.tsx b/app/src/screens/contract-permissions/ContractPermissionsScreen.tsx index 13e24efca..53a1bfaae 100644 --- a/app/src/screens/contract-permissions/ContractPermissionsScreen.tsx +++ b/app/src/screens/contract-permissions/ContractPermissionsScreen.tsx @@ -19,12 +19,27 @@ import { Appbar } from '~/components/Appbar/Appbar'; import { useAddressLabel } from '~/components/address/AddressLabel'; import { SpendingLimit } from './SpendingLimit'; import { ListHeader } from '~/components/list/ListHeader'; -import { useMaybeToken } from '@token/useToken'; import { getFunctionSelector } from 'viem'; import { ContractFunction } from '@api/contracts/types'; import { ScrollView } from 'react-native'; import { ListItem } from '~/components/list/ListItem'; import { Switch } from 'react-native-paper'; +import { gql } from '@api/gen'; +import { useSuspenseQuery } from '@apollo/client'; +import { + ContractPermissionsScreenQuery, + ContractPermissionsScreenQueryVariables, +} from '@api/gen/graphql'; +import { ContractPermissionsScreenDocument } from '@api/generated'; + +gql(/* GraphQL */ ` + query ContractPermissionsScreen($contract: Address!) { + token(input: { address: $contract }) { + id + ...SpendingLimit_token + } + } +`); const ERC20_FUNCTIONS: ContractFunction[] = ERC20_ABI.filter( (abi): abi is Extract => abi.type === 'function', @@ -42,7 +57,11 @@ export type ContractPermissionsScreenProps = StackNavigatorScreenProps<'Contract export const ContractPermissionsScreen = withSuspense( ({ route }: ContractPermissionsScreenProps) => { const { contract } = route.params; - const isToken = !!useMaybeToken(contract); + + const { token } = useSuspenseQuery< + ContractPermissionsScreenQuery, + ContractPermissionsScreenQueryVariables + >(ContractPermissionsScreenDocument, { variables: { contract } }).data; const [{ permissions }, updatePolicy] = useImmerAtom(POLICY_DRAFT_ATOM); @@ -50,7 +69,7 @@ export const ContractPermissionsScreen = withSuspense( const functions = filterFirst( [ ...useContractFunctions(contract), - ...(isToken ? ERC20_FUNCTIONS : []), + ...(token ? ERC20_FUNCTIONS : []), ...Object.keys(target?.functions ?? []).map((selector) => ({ selector: selector as Selector, abi: undefined, @@ -67,7 +86,7 @@ export const ContractPermissionsScreen = withSuspense( - + {token && } Actions diff --git a/app/src/screens/contract-permissions/SpendingLimit.tsx b/app/src/screens/contract-permissions/SpendingLimit.tsx index 8161e58c1..2566d452a 100644 --- a/app/src/screens/contract-permissions/SpendingLimit.tsx +++ b/app/src/screens/contract-permissions/SpendingLimit.tsx @@ -1,7 +1,6 @@ import { makeStyles } from '@theme/makeStyles'; -import { useMaybeToken } from '@token/useToken'; import { useImmerAtom } from 'jotai-immer'; -import { Address, TransferLimit } from 'lib'; +import { TransferLimit } from 'lib'; import { Duration } from 'luxon'; import { View } from 'react-native'; import { BasicTextField } from '~/components/fields/BasicTextField'; @@ -10,6 +9,15 @@ import { ListHeader } from '~/components/list/ListHeader'; import { POLICY_DRAFT_ATOM } from '../policy/PolicyDraft'; import { useBigIntInput } from '~/components/fields/useBigIntInput'; import { ClockOutlineIcon } from '@theme/icons'; +import { FragmentType, gql, useFragment } from '@api/gen'; + +const Fragment = gql(/* GraphQL */ ` + fragment SpendingLimit_token on Token { + id + address + decimals + } +`); const DEFAULT_DURATION = Duration.fromObject({ day: 1 }); @@ -23,34 +31,32 @@ const DURATIONS = [ ] as const; export interface SpendingLimitProps { - contract: Address; + token: FragmentType; } -export function SpendingLimit({ contract }: SpendingLimitProps) { +export function SpendingLimit(props: SpendingLimitProps) { const styles = useStyles(); - const token = useMaybeToken(contract); + const t = useFragment(Fragment, props.token); const [policy, updatePolicy] = useImmerAtom(POLICY_DRAFT_ATOM); - const limit: TransferLimit | undefined = policy.permissions.transfers.limits[contract]; + const limit: TransferLimit | undefined = policy.permissions.transfers.limits[t.address]; const inputProps = useBigIntInput({ value: limit?.amount, - decimals: token?.decimals ?? 0, + decimals: t.decimals, onChange: (amount) => updatePolicy(({ permissions: { transfers } }) => { if (amount !== undefined) { - transfers.limits[contract] = { + transfers.limits[t.address] = { amount, - duration: transfers.limits[contract]?.duration ?? DEFAULT_DURATION.as('seconds'), + duration: transfers.limits[t.address]?.duration ?? DEFAULT_DURATION.as('seconds'), }; } else { - delete transfers.limits[contract]; + delete transfers.limits[t.address]; } }), }); - if (!token) return null; - return ( <> Spending limit @@ -68,8 +74,8 @@ export function SpendingLimit({ contract }: SpendingLimitProps) { value={limit ? Duration.fromObject({ seconds: limit.duration }) : DEFAULT_DURATION} onChange={(duration) => updatePolicy(({ permissions: { transfers } }) => { - transfers.limits[contract] = { - amount: transfers.limits[contract]?.amount ?? 0n, + transfers.limits[t.address] = { + amount: transfers.limits[t.address]?.amount ?? 0n, duration: duration.as('seconds'), }; }) diff --git a/app/src/screens/home/AccountValue.tsx b/app/src/screens/home/AccountValue.tsx index 5e3793662..9321c0614 100644 --- a/app/src/screens/home/AccountValue.tsx +++ b/app/src/screens/home/AccountValue.tsx @@ -1,6 +1,6 @@ import { FragmentType, gql, useFragment } from '@api/gen'; import { makeStyles } from '@theme/makeStyles'; -import { getTokenValue } from '@token/token'; +import { tokenToFiat } from 'lib'; import { Text } from 'react-native-paper'; import { FiatValue } from '~/components/fiat/FiatValue'; @@ -27,12 +27,7 @@ export function AccountValue(props: AccountValueProps) { const { tokens } = useFragment(FragmentDoc, props.tokensQuery); const total = tokens.reduce( - (sum, token) => - getTokenValue({ - amount: token.balance, - price: token.price?.current ?? 0, - decimals: token.decimals, - }) + sum, + (sum, token) => tokenToFiat(token.balance, token.price?.current ?? 0, token.decimals) + sum, 0, ); diff --git a/app/src/screens/home/Tabs/TokensTab.tsx b/app/src/screens/home/Tabs/TokensTab.tsx index 320fc9c4d..693a054ba 100644 --- a/app/src/screens/home/Tabs/TokensTab.tsx +++ b/app/src/screens/home/Tabs/TokensTab.tsx @@ -6,7 +6,7 @@ import { withSuspense } from '~/components/skeleton/withSuspense'; import { TabScreenSkeleton } from '~/components/tab/TabScreenSkeleton'; import { StyleSheet } from 'react-native'; import { Text } from 'react-native-paper'; -import { Address, getTokenValue } from 'lib'; +import { Address, tokenToFiat } from 'lib'; import { gql } from '@api/gen'; import { useSuspenseQuery } from '@apollo/client'; import { TokensTabQuery, TokensTabQueryVariables } from '@api/gen/graphql'; @@ -42,11 +42,7 @@ export const TokensTab = withSuspense( const tokens = data.tokens .map((t) => ({ ...t, - value: getTokenValue({ - amount: t.balance, - price: t.price?.current ?? 0, - decimals: t.decimals, - }), + value: tokenToFiat(t.balance, t.price?.current ?? 0, t.decimals), })) .sort((a, b) => b.value - a.value); diff --git a/app/src/screens/proposal/TransactionTab.tsx b/app/src/screens/proposal/TransactionTab.tsx index a012b31ae..5e703f5dc 100644 --- a/app/src/screens/proposal/TransactionTab.tsx +++ b/app/src/screens/proposal/TransactionTab.tsx @@ -8,17 +8,16 @@ import { Timestamp } from '~/components/format/Timestamp'; import { ListItem, ListItemProps } from '~/components/list/ListItem'; import { withSuspense } from '~/components/skeleton/withSuspense'; import { TabScreenSkeleton } from '~/components/tab/TabScreenSkeleton'; -import { TokenAmount } from '~/components/token/TokenAmount2'; +import { TokenAmount } from '~/components/token/TokenAmount'; import { TokenIcon } from '~/components/token/TokenIcon/TokenIcon'; import { TabNavigatorScreenProp } from './Tabs'; import { makeStyles } from '@theme/makeStyles'; -import { Hex, asBigInt } from 'lib'; +import { Hex, asBigInt, tokenToFiat } from 'lib'; import { ReactNode } from 'react'; import { gql, useFragment } from '@api/gen'; import { useSuspenseQuery } from '@apollo/client'; import { TransactionTabQuery, TransactionTabQueryVariables } from '@api/gen/graphql'; import { TransactionTabDocument, useTransactionTabSubscriptionSubscription } from '@api/generated'; -import { getTokenValue } from '@token/token'; const FragmentDoc = gql(/* GraphQL */ ` fragment TransactionTab_TransactionProposalFragment on TransactionProposal { @@ -177,11 +176,7 @@ export const TransactionTab = withSuspense(({ route }: TransactionTabProps) => { supporting={} trailing={ } /> @@ -192,11 +187,7 @@ export const TransactionTab = withSuspense(({ route }: TransactionTabProps) => { supporting={} trailing={ } /> diff --git a/app/src/screens/send/SendScreen.tsx b/app/src/screens/send/SendScreen.tsx index 2e425d2ea..931959f21 100644 --- a/app/src/screens/send/SendScreen.tsx +++ b/app/src/screens/send/SendScreen.tsx @@ -1,7 +1,7 @@ import { usePropose } from '@api/proposal'; import { CloseIcon } from '@theme/icons'; import { parseUnits } from 'ethers/lib/utils'; -import { Address, FIAT_DECIMALS, valueAsTokenAmount } from 'lib'; +import { Address, FIAT_DECIMALS, fiatToToken } from 'lib'; import { useState } from 'react'; import { StyleSheet, View } from 'react-native'; import { Appbar, Divider } from 'react-native-paper'; @@ -72,7 +72,7 @@ export const SendScreen = withSuspense( const tokenAmount = type === InputType.Token ? parseUnits(inputAmount, token.decimals).toBigInt() - : valueAsTokenAmount(parseFloat(inputAmount), token.price?.current ?? 0, token.decimals); + : fiatToToken(parseFloat(inputAmount), token.price?.current ?? 0, token.decimals); return ( diff --git a/app/src/screens/swap/SwapScreen.tsx b/app/src/screens/swap/SwapScreen.tsx index a2728ce21..8a79eb785 100644 --- a/app/src/screens/swap/SwapScreen.tsx +++ b/app/src/screens/swap/SwapScreen.tsx @@ -1,6 +1,6 @@ import { usePropose } from '@api/proposal'; import { parseUnits } from 'ethers/lib/utils'; -import { Address, FIAT_DECIMALS, valueAsTokenAmount } from 'lib'; +import { Address, FIAT_DECIMALS, fiatToToken } from 'lib'; import { useState } from 'react'; import { InputType, InputsView } from '~/components/InputsView'; import { ScreenSkeleton } from '~/components/skeleton/ScreenSkeleton'; @@ -88,7 +88,7 @@ export const SwapScreen = withSuspense(({ route, navigation: { navigate } }: Swa const fromAmount = type === InputType.Token ? parseUnits(fromInput, from.decimals).toBigInt() - : valueAsTokenAmount(parseFloat(fromInput), from.price?.current ?? 0, from.decimals); + : fiatToToken(parseFloat(fromInput), from.price?.current ?? 0, from.decimals); return ( diff --git a/app/src/screens/swap/ToTokenItem.tsx b/app/src/screens/swap/ToTokenItem.tsx index 94a28d886..83e2bdf38 100644 --- a/app/src/screens/swap/ToTokenItem.tsx +++ b/app/src/screens/swap/ToTokenItem.tsx @@ -1,5 +1,5 @@ import { FragmentType, gql, useFragment } from '@api/gen'; -import { Address, convertToDecimals } from 'lib'; +import { Address, tokenToToken } from 'lib'; import { useFormattedNumber } from '~/components/format/FormattedNumber'; import { ListItem, ListItemProps } from '~/components/list/ListItem'; import { ListItemSkeleton } from '~/components/list/ListItemSkeleton'; @@ -62,7 +62,7 @@ function ToTokenItem({ from: { token: from.address, amount: ratioFromAmount }, }); const ratio = - (ratioToAmount * RATIO_FACTOR) / convertToDecimals(ratioFromAmount, from.decimals, to.decimals); + (ratioToAmount * RATIO_FACTOR) / tokenToToken(ratioFromAmount, from.decimals, to.decimals); return ( - BigInt(Math.floor((typeof value === 'number' ? value : parseFloat(value)) * multiplier)); - -// export const asFiat = (value: bigint) => value / BigInt(FIAT_DECIMALS); - -export const fiatToToken = (fiat: bigint, fiatPrice: bigint, token: Token): bigint => - (fiat * 10n ** BigInt(token.decimals)) / fiatPrice; - -export const tokenToFiat = (amount: bigint, price: bigint, decimals: number): bigint => - (amount * price) / 10n ** BigInt(decimals); - -export const valueAsTokenAmount = (value: number, price: number, decimals: number): bigint => - (fiatAsBigInt(value) * 10n ** BigInt(decimals)) / fiatAsBigInt(price); diff --git a/app/src/util/token/token.ts b/app/src/util/token/token.ts deleted file mode 100644 index 95864ddd4..000000000 --- a/app/src/util/token/token.ts +++ /dev/null @@ -1,94 +0,0 @@ -import assert from 'assert'; -import { - Address, - createIsObj, - Erc20__factory, - isAddress, - ChainKey, - tryAsAddress, - BigIntlike, - asBigInt, -} from 'lib'; -import _ from 'lodash'; -import { formatUnits } from 'viem'; -import { CHAIN } from '~/util/network/provider'; -import { FIAT_DECIMALS, fiatAsBigInt } from './fiat'; - -export type TokenType = 'Native' | 'ERC20'; - -export interface TokenUnit { - symbol: string; - decimals: number; -} - -export interface Token extends TokenUnit { - type: TokenType; - name: string; - symbol: string; - decimals: number; - address: Address; // Current chain address - addresses: Partial>; - iconUri: string; - units: [TokenUnit, ...TokenUnit[]]; -} - -export const isToken = createIsObj( - ['type', 'string'], - ['name', 'string'], - ['symbol', 'string'], - ['decimals', 'number'], - ['address', isAddress], - ['iconUri', 'string'], -); - -type TokenDef = Pick & { - type?: TokenType; - addresses: Partial>; - iconUri?: string; - units?: TokenUnit[]; -}; - -export const asToken = (def: TokenDef): Token => { - const addresses = _.mapValues(def.addresses, tryAsAddress); - - const address = addresses[CHAIN.key]; - assert(address, `Token '${def.name}' doesn't support current chain '${CHAIN.name}'`); - - const baseUnit: TokenUnit = { symbol: def.symbol, decimals: def.decimals }; - - return { - type: 'ERC20', - ...def, - address, - addresses, - iconUri: - def.iconUri ?? - `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${def.addresses.mainnet}/logo.png`, - units: [baseUnit, ...(def.units ?? [])], - }; -}; - -export const ERC20_INTERFACE = Erc20__factory.createInterface(); - -export const convertDecimals = ( - amount: bigint, - curDecimals: number, - newDecimals: number, -): bigint => { - const decimalsDiff = curDecimals - newDecimals; - if (decimalsDiff === 0) return amount; - - const factor = 10n ** BigInt(Math.abs(decimalsDiff)); - - return decimalsDiff >= 0 ? amount / factor : amount * factor; -}; - -export interface TokenValueOptions { - amount: BigIntlike; - decimals: number; - price: number; -} - -export function getTokenValue({ amount, decimals, price }: TokenValueOptions): number { - return parseFloat(formatUnits(asBigInt(amount) * fiatAsBigInt(price), decimals + FIAT_DECIMALS)); -} diff --git a/lib/jest.config.ts b/lib/jest.config.ts index 54a8bcd92..b66556937 100644 --- a/lib/jest.config.ts +++ b/lib/jest.config.ts @@ -3,7 +3,7 @@ import { Config } from '@jest/types'; const config: Config.InitialOptions = { preset: 'ts-jest', testEnvironment: 'node', - testRegex: 'src/.*\\.test\\.ts$', + testRegex: 'src/.*\\.spec\\.ts$', }; export default config; diff --git a/lib/src/convert.spec.ts b/lib/src/convert.spec.ts new file mode 100644 index 000000000..059043cf5 --- /dev/null +++ b/lib/src/convert.spec.ts @@ -0,0 +1,28 @@ +import { parseUnits } from 'viem'; +import { tokenToToken, fiatToToken, tokenToFiat } from './convert'; + +const USDC_DECIMALS = 6; +const ETH_DECIMALS = 18; +const ETH_PRICE = 2150; + +describe('convert', () => { + it('token to token', () => { + const fiveUsdc = parseUnits('5', USDC_DECIMALS); + + expect( + tokenToToken( + tokenToToken(fiveUsdc, USDC_DECIMALS, ETH_DECIMALS), + ETH_DECIMALS, + USDC_DECIMALS, + ), + ).toEqual(fiveUsdc); + }); + + it('fiat to token', () => { + expect(fiatToToken(645, ETH_PRICE, ETH_DECIMALS)).toEqual(parseUnits('0.3', ETH_DECIMALS)); + }); + + it('token to fiat', () => { + expect(tokenToFiat(parseUnits('0.3', ETH_DECIMALS), ETH_PRICE, ETH_DECIMALS)).toEqual(645); + }); +}); diff --git a/lib/src/convert.ts b/lib/src/convert.ts new file mode 100644 index 000000000..65e44d095 --- /dev/null +++ b/lib/src/convert.ts @@ -0,0 +1,35 @@ +import { formatUnits } from 'viem'; +import { BigIntlike } from './bigint'; + +export const FIAT_DECIMALS = 16; + +export function tokenToToken(amount: BigIntlike, curDecimals: number, newDecimals: number): bigint { + const decimalsDiff = curDecimals - newDecimals; + const factor = 10n ** BigInt(Math.abs(decimalsDiff)); + + return decimalsDiff >= 0 ? BigInt(amount) / factor : BigInt(amount) * factor; +} + +export function fiatToToken(value: number, price: number, decimals: number): bigint { + return ( + (numberToBigInt(value, FIAT_DECIMALS) * 10n ** BigInt(decimals)) / + numberToBigInt(price, FIAT_DECIMALS) + ); +} + +export function tokenToFiat(amount: BigIntlike, price: number, decimals: number): number { + return bigIntToNumber( + BigInt(amount) * numberToBigInt(price, FIAT_DECIMALS), + FIAT_DECIMALS + decimals, + ); +} + +function numberToBigInt(value: string | number, decimals: number): bigint { + return BigInt( + Math.floor((typeof value === 'number' ? value : parseFloat(value)) * 10 ** decimals), + ); +} + +function bigIntToNumber(value: bigint, decimals: number): number { + return parseFloat(formatUnits(value, decimals)); +} diff --git a/lib/src/index.ts b/lib/src/index.ts index 12ccc8730..80d06a085 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -28,6 +28,7 @@ export * from './bigint'; export * from './bytes'; export * from './operation'; export * from './chain'; +export * from './convert'; export * from './decode'; export * from './deploy'; export * from './errors'; diff --git a/lib/src/signature.test.ts b/lib/src/signature.test.ts deleted file mode 100644 index 0bf74f204..000000000 --- a/lib/src/signature.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -describe('example', () => { - it('pass', () => { - // - }); -});