diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index f83b1e8f..7abf2904 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { RestClient, TxsResponse, types } from "@cosmwasm/sdk"; +import { RestClient, TxsResponse } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -36,7 +36,7 @@ import { Stream } from "xstream"; import { CosmosBech32Prefix, decodeCosmosPubkey, pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { decodeAmount, parseTxsResponse } from "./decode"; -import { accountToNonce } from "./types"; +import { accountToNonce, TokenInfo } from "./types"; interface ChainData { readonly chainId: ChainId; @@ -66,7 +66,7 @@ function buildQueryString({ return components.filter(Boolean).join("&"); } -export type TokenConfiguration = readonly (types.TokenInfo & { readonly name: string })[]; +export type TokenConfiguration = (TokenInfo & { readonly name: string })[]; export class CosmWasmConnection implements BlockchainConnection { // we must know prefix and tokens a priori to understand the chain @@ -88,7 +88,7 @@ export class CosmWasmConnection implements BlockchainConnection { private readonly restClient: RestClient; private readonly chainData: ChainData; private readonly _prefix: CosmosBech32Prefix; - private readonly tokenInfo: readonly types.TokenInfo[]; + private readonly tokenInfo: readonly TokenInfo[]; // these are derived from arguments (cached for use in multiple functions) private readonly primaryToken: Token; diff --git a/packages/bcp/src/decode.ts b/packages/bcp/src/decode.ts index 6fa4ead7..8239a9e2 100644 --- a/packages/bcp/src/decode.ts +++ b/packages/bcp/src/decode.ts @@ -1,4 +1,4 @@ -import { coinToDecimal, TxsResponse, types } from "@cosmwasm/sdk"; +import { TxsResponse, types } from "@cosmwasm/sdk"; import { Address, Algorithm, @@ -17,7 +17,7 @@ import { TransactionId, UnsignedTransaction, } from "@iov/bcp"; -import { Encoding } from "@iov/encoding"; +import { Decimal, Encoding } from "@iov/encoding"; import { TokenInfos } from "./types"; @@ -54,6 +54,15 @@ export function decodeFullSignature(signature: types.StdSignature, nonce: number }; } +export function coinToDecimal(tokens: TokenInfos, coin: types.Coin): readonly [Decimal, string] { + const match = tokens.find(({ denom }) => denom === coin.denom); + if (!match) { + throw Error(`unknown denom: ${coin.denom}`); + } + const value = Decimal.fromAtomics(coin.amount, match.fractionalDigits); + return [value, match.ticker]; +} + export function decodeAmount(tokens: TokenInfos, coin: types.Coin): Amount { const [value, ticker] = coinToDecimal(tokens, coin); return { diff --git a/packages/bcp/src/encode.ts b/packages/bcp/src/encode.ts index d8793ad0..94288c48 100644 --- a/packages/bcp/src/encode.ts +++ b/packages/bcp/src/encode.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { decimalToCoin, types } from "@cosmwasm/sdk"; +import { types } from "@cosmwasm/sdk"; import { Algorithm, Amount, @@ -34,6 +34,22 @@ export function encodePubkey(pubkey: PubkeyBundle): types.PubKey { } } +export function decimalToCoin(lookup: TokenInfos, value: Decimal, ticker: string): types.Coin { + const match = lookup.find(token => token.ticker === ticker); + if (!match) { + throw Error(`unknown ticker: ${ticker}`); + } + if (match.fractionalDigits !== value.fractionalDigits) { + throw new Error( + "Mismatch in fractional digits between token and value. If you really want, implement a conversion here. However, this indicates a bug in the caller code.", + ); + } + return { + denom: match.denom, + amount: value.atomics, + }; +} + export function encodeAmount(amount: Amount, tokens: TokenInfos): types.Coin { return decimalToCoin( tokens, diff --git a/packages/bcp/src/types.ts b/packages/bcp/src/types.ts index eb90b68f..32133828 100644 --- a/packages/bcp/src/types.ts +++ b/packages/bcp/src/types.ts @@ -1,7 +1,21 @@ -import { types } from "@cosmwasm/sdk"; import { Nonce } from "@iov/bcp"; -export type TokenInfos = ReadonlyArray; +export interface TokenInfo { + readonly denom: string; + readonly ticker: string; + /** + * The number of fractional digits the token supports. + * + * A quantity is expressed as atomic units. 10^fractionalDigits of those + * atomic units make up 1 token. + * + * E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000 + * the last 18 digits are the fractional part and the rest the wole part. + */ + readonly fractionalDigits: number; +} + +export type TokenInfos = ReadonlyArray; // tslint:disable-next-line:no-bitwise const maxAcct = 1 << 23; diff --git a/packages/bcp/types/cosmwasmconnection.d.ts b/packages/bcp/types/cosmwasmconnection.d.ts index b84557df..c3c2f616 100644 --- a/packages/bcp/types/cosmwasmconnection.d.ts +++ b/packages/bcp/types/cosmwasmconnection.d.ts @@ -1,4 +1,3 @@ -import { types } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -22,7 +21,8 @@ import { } from "@iov/bcp"; import { Stream } from "xstream"; import { CosmosBech32Prefix } from "./address"; -export declare type TokenConfiguration = readonly (types.TokenInfo & { +import { TokenInfo } from "./types"; +export declare type TokenConfiguration = (TokenInfo & { readonly name: string; })[]; export declare class CosmWasmConnection implements BlockchainConnection { diff --git a/packages/bcp/types/decode.d.ts b/packages/bcp/types/decode.d.ts index af8f43be..60f9b198 100644 --- a/packages/bcp/types/decode.d.ts +++ b/packages/bcp/types/decode.d.ts @@ -12,10 +12,12 @@ import { SignedTransaction, UnsignedTransaction, } from "@iov/bcp"; +import { Decimal } from "@iov/encoding"; import { TokenInfos } from "./types"; export declare function decodePubkey(pubkey: types.PubKey): PubkeyBundle; export declare function decodeSignature(signature: string): SignatureBytes; export declare function decodeFullSignature(signature: types.StdSignature, nonce: number): FullSignature; +export declare function coinToDecimal(tokens: TokenInfos, coin: types.Coin): readonly [Decimal, string]; export declare function decodeAmount(tokens: TokenInfos, coin: types.Coin): Amount; export declare function parseMsg(msg: types.Msg, chainId: ChainId, tokens: TokenInfos): SendTransaction; export declare function parseFee(fee: types.StdFee, tokens: TokenInfos): Fee; diff --git a/packages/bcp/types/encode.d.ts b/packages/bcp/types/encode.d.ts index 72e10ba8..7af2c690 100644 --- a/packages/bcp/types/encode.d.ts +++ b/packages/bcp/types/encode.d.ts @@ -1,7 +1,9 @@ import { types } from "@cosmwasm/sdk"; import { Amount, Fee, FullSignature, PubkeyBundle, SignedTransaction, UnsignedTransaction } from "@iov/bcp"; +import { Decimal } from "@iov/encoding"; import { TokenInfos } from "./types"; export declare function encodePubkey(pubkey: PubkeyBundle): types.PubKey; +export declare function decimalToCoin(lookup: TokenInfos, value: Decimal, ticker: string): types.Coin; export declare function encodeAmount(amount: Amount, tokens: TokenInfos): types.Coin; export declare function encodeFee(fee: Fee, tokens: TokenInfos): types.StdFee; export declare function encodeFullSignature(fullSignature: FullSignature): types.StdSignature; diff --git a/packages/bcp/types/types.d.ts b/packages/bcp/types/types.d.ts index b419ece0..e8ac6ce2 100644 --- a/packages/bcp/types/types.d.ts +++ b/packages/bcp/types/types.d.ts @@ -1,6 +1,19 @@ -import { types } from "@cosmwasm/sdk"; import { Nonce } from "@iov/bcp"; -export declare type TokenInfos = ReadonlyArray; +export interface TokenInfo { + readonly denom: string; + readonly ticker: string; + /** + * The number of fractional digits the token supports. + * + * A quantity is expressed as atomic units. 10^fractionalDigits of those + * atomic units make up 1 token. + * + * E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000 + * the last 18 digits are the fractional part and the rest the wole part. + */ + readonly fractionalDigits: number; +} +export declare type TokenInfos = ReadonlyArray; export interface NonceInfo { readonly account_number: string; readonly sequence: string; diff --git a/packages/sdk/src/decoding.ts b/packages/sdk/src/decoding.ts index 701e1e69..e69de29b 100644 --- a/packages/sdk/src/decoding.ts +++ b/packages/sdk/src/decoding.ts @@ -1,13 +0,0 @@ -import { Decimal } from "@iov/encoding"; -import amino from "@tendermint/amino-js"; - -import { TokenInfo } from "./types"; - -export function coinToDecimal(tokens: readonly TokenInfo[], coin: amino.Coin): readonly [Decimal, string] { - const match = tokens.find(({ denom }) => denom === coin.denom); - if (!match) { - throw Error(`unknown denom: ${coin.denom}`); - } - const value = Decimal.fromAtomics(coin.amount, match.fractionalDigits); - return [value, match.ticker]; -} diff --git a/packages/sdk/src/encoding.ts b/packages/sdk/src/encoding.ts index c4bed170..e69de29b 100644 --- a/packages/sdk/src/encoding.ts +++ b/packages/sdk/src/encoding.ts @@ -1,20 +0,0 @@ -import { Decimal } from "@iov/encoding"; -import amino from "@tendermint/amino-js"; - -import { TokenInfo } from "./types"; - -export function decimalToCoin(lookup: readonly TokenInfo[], value: Decimal, ticker: string): amino.Coin { - const match = lookup.find(token => token.ticker === ticker); - if (!match) { - throw Error(`unknown ticker: ${ticker}`); - } - if (match.fractionalDigits !== value.fractionalDigits) { - throw new Error( - "Mismatch in fractional digits between token and value. If you really want, implement a conversion here. However, this indicates a bug in the caller code.", - ); - } - return { - denom: match.denom, - amount: value.atomics, - }; -} diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index a38d5033..d97b584b 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,4 @@ -export { coinToDecimal } from "./decoding"; -export { decimalToCoin } from "./encoding"; -export { RestClient, TxsResponse } from "./restclient"; - import * as types from "./types"; + +export { RestClient, TxsResponse } from "./restclient"; export { types }; diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index a99179df..7dea1856 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -67,18 +67,3 @@ export function isAminoStdTx(txValue: unknown): txValue is StdTx { typeof memo === "string" && Array.isArray(msg) && typeof fee === "object" && Array.isArray(signatures) ); } - -export interface TokenInfo { - readonly denom: string; - readonly ticker: string; - /** - * The number of fractional digits the token supports. - * - * A quantity is expressed as atomic units. 10^fractionalDigits of those - * atomic units make up 1 token. - * - * E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000 - * the last 18 digits are the fractional part and the rest the wole part. - */ - readonly fractionalDigits: number; -} diff --git a/packages/sdk/types/decoding.d.ts b/packages/sdk/types/decoding.d.ts index 6c1552eb..e69de29b 100644 --- a/packages/sdk/types/decoding.d.ts +++ b/packages/sdk/types/decoding.d.ts @@ -1,7 +0,0 @@ -import { Decimal } from "@iov/encoding"; -import amino from "@tendermint/amino-js"; -import { TokenInfo } from "./types"; -export declare function coinToDecimal( - tokens: readonly TokenInfo[], - coin: amino.Coin, -): readonly [Decimal, string]; diff --git a/packages/sdk/types/encoding.d.ts b/packages/sdk/types/encoding.d.ts index c8e3334e..e69de29b 100644 --- a/packages/sdk/types/encoding.d.ts +++ b/packages/sdk/types/encoding.d.ts @@ -1,8 +0,0 @@ -import { Decimal } from "@iov/encoding"; -import amino from "@tendermint/amino-js"; -import { TokenInfo } from "./types"; -export declare function decimalToCoin( - lookup: readonly TokenInfo[], - value: Decimal, - ticker: string, -): amino.Coin; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 13b0904b..b441abf5 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,6 +1,3 @@ -export { coinToDecimal } from "./decoding"; -export { decimalToCoin } from "./encoding"; -export { RestClient, TxsResponse } from "./restclient"; import * as types from "./types"; +export { RestClient, TxsResponse } from "./restclient"; export { types }; -export { isAminoStdTx } from "./types"; diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index 1f0af1a5..a5e5672d 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -48,17 +48,3 @@ export declare type AminoTx = Tx & { readonly value: StdTx; }; export declare function isAminoStdTx(txValue: unknown): txValue is StdTx; -export interface TokenInfo { - readonly denom: string; - readonly ticker: string; - /** - * The number of fractional digits the token supports. - * - * A quantity is expressed as atomic units. 10^fractionalDigits of those - * atomic units make up 1 token. - * - * E.g. in Ethereum 10^18 wei are 1 ETH and from the quantity 123000000000000000000 - * the last 18 digits are the fractional part and the rest the wole part. - */ - readonly fractionalDigits: number; -}