diff --git a/packages/bcp/src/decode.ts b/packages/bcp/src/decode.ts index 9fb0869a..002cc5b3 100644 --- a/packages/bcp/src/decode.ts +++ b/packages/bcp/src/decode.ts @@ -13,13 +13,14 @@ import { SendTransaction, SignatureBytes, SignedTransaction, + TokenTicker, TransactionId, UnsignedTransaction, } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; import amino from "@tendermint/amino-js"; -import { coinToAmount, TokenInfos } from "./types"; +import { coinToDecimal, TokenInfos } from "./types"; const { fromBase64 } = Encoding; @@ -43,7 +44,12 @@ export function decodeFullSignature(signature: amino.StdSignature, nonce: number } export function decodeAmount(tokens: TokenInfos, coin: amino.Coin): Amount { - return coinToAmount(tokens, coin); + const [value, ticker] = coinToDecimal(tokens, coin); + return { + quantity: value.atomics, + fractionalDigits: value.fractionalDigits, + tokenTicker: ticker as TokenTicker, + }; } export function parseMsg(msg: amino.Msg, chainId: ChainId, tokens: TokenInfos): SendTransaction { diff --git a/packages/bcp/src/encode.ts b/packages/bcp/src/encode.ts index 28843930..3ce2ebcf 100644 --- a/packages/bcp/src/encode.ts +++ b/packages/bcp/src/encode.ts @@ -11,10 +11,10 @@ import { UnsignedTransaction, } from "@iov/bcp"; import { Secp256k1 } from "@iov/crypto"; -import { Encoding } from "@iov/encoding"; +import { Decimal, Encoding } from "@iov/encoding"; import amino from "@tendermint/amino-js"; -import { amountToCoin, TokenInfos } from "./types"; +import { decimalToCoin, TokenInfos } from "./types"; const { toBase64 } = Encoding; @@ -36,7 +36,11 @@ export function encodePubkey(pubkey: PubkeyBundle): amino.PubKey { } export function encodeAmount(amount: Amount, tokens: TokenInfos): amino.Coin { - return amountToCoin(tokens, amount); + return decimalToCoin( + tokens, + Decimal.fromAtomics(amount.quantity, amount.fractionalDigits), + amount.tokenTicker, + ); } export function encodeFee(fee: Fee, tokens: TokenInfos): amino.StdFee { diff --git a/packages/bcp/src/types.ts b/packages/bcp/src/types.ts index d4035e6c..c2f5edd1 100644 --- a/packages/bcp/src/types.ts +++ b/packages/bcp/src/types.ts @@ -1,31 +1,33 @@ import { TokenInfo } from "@cosmwasm/sdk"; -import { Amount, Nonce, TokenTicker } from "@iov/bcp"; +import { Nonce } from "@iov/bcp"; +import { Decimal } from "@iov/encoding"; import amino from "@tendermint/amino-js"; export type TokenInfos = ReadonlyArray; -// TODO: return null vs throw exception for undefined??? -export function amountToCoin(lookup: ReadonlyArray, amount: Amount): amino.Coin { - const match = lookup.find(({ ticker }) => ticker === amount.tokenTicker); +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: ${amount.tokenTicker}`); + 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: amount.quantity, + amount: value.atomics, }; } -export function coinToAmount(tokens: TokenInfos, coin: amino.Coin): Amount { +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}`); } - return { - tokenTicker: match.ticker as TokenTicker, - fractionalDigits: match.fractionalDigits, - quantity: coin.amount, - }; + const value = Decimal.fromAtomics(coin.amount, match.fractionalDigits); + return [value, match.ticker]; } // tslint:disable-next-line:no-bitwise diff --git a/packages/bcp/types/types.d.ts b/packages/bcp/types/types.d.ts index 7191f61c..6a8f6f49 100644 --- a/packages/bcp/types/types.d.ts +++ b/packages/bcp/types/types.d.ts @@ -1,9 +1,17 @@ import { TokenInfo } from "@cosmwasm/sdk"; -import { Amount, Nonce } from "@iov/bcp"; +import { Nonce } from "@iov/bcp"; +import { Decimal } from "@iov/encoding"; import amino from "@tendermint/amino-js"; export declare type TokenInfos = ReadonlyArray; -export declare function amountToCoin(lookup: ReadonlyArray, amount: Amount): amino.Coin; -export declare function coinToAmount(tokens: TokenInfos, coin: amino.Coin): Amount; +export declare function decimalToCoin( + lookup: readonly TokenInfo[], + value: Decimal, + ticker: string, +): amino.Coin; +export declare function coinToDecimal( + tokens: readonly TokenInfo[], + coin: amino.Coin, +): readonly [Decimal, string]; export interface NonceInfo { readonly account_number: string; readonly sequence: string;