Add ERC20 support in codec

This commit is contained in:
Simon Warta 2020-02-10 17:43:40 +01:00
parent 220a8ddd98
commit 0fe0d3bec3
3 changed files with 75 additions and 14 deletions

View File

@ -1,16 +1,16 @@
import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk";
import { PostableBytes, PrehashType } from "@iov/bcp";
import { Address, PostableBytes, PrehashType, SendTransaction, TokenTicker } from "@iov/bcp";
import { Encoding } from "@iov/encoding";
import { CosmWasmCodec } from "./cosmwasmcodec";
import { chainId, nonce, sendTxJson, signedTxBin, signedTxEncodedJson, signedTxJson } from "./testdata.spec";
import { BankTokens } from "./types";
import { BankToken, Erc20Token } from "./types";
const { toUtf8 } = Encoding;
const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix;
const defaultTokens: BankTokens = [
const defaultBankTokens: readonly BankToken[] = [
{
fractionalDigits: 6,
ticker: "ATOM",
@ -18,8 +18,26 @@ const defaultTokens: BankTokens = [
},
];
const defaultErc20Tokens: readonly Erc20Token[] = [
{
contractAddress: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
fractionalDigits: 5,
ticker: "ASH",
},
{
contractAddress: "cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd",
fractionalDigits: 0,
ticker: "BASH",
},
{
contractAddress: "cosmos18r5szma8hm93pvx6lwpjwyxruw27e0k5uw835c",
fractionalDigits: 18,
ticker: "CASH",
},
];
describe("CosmWasmCodec", () => {
const codec = new CosmWasmCodec(defaultPrefix, defaultTokens);
const codec = new CosmWasmCodec(defaultPrefix, defaultBankTokens, defaultErc20Tokens);
describe("isValidAddress", () => {
it("accepts valid addresses", () => {
@ -48,6 +66,38 @@ describe("CosmWasmCodec", () => {
};
expect(codec.bytesToSign(sendTxJson, nonce)).toEqual(expected);
});
it("works for ERC20 send", () => {
const bashSendTx: SendTransaction = {
kind: "bcp/send",
chainId: chainId,
sender: "cosmos1txqfn5jmcts0x0q7krdxj8tgf98tj0965vqlmq" as Address,
recipient: "cosmos1dddd" as Address,
memo: "My first BASH payment",
amount: {
fractionalDigits: 6,
quantity: "345",
tokenTicker: "BASH" as TokenTicker,
},
fee: {
tokens: {
fractionalDigits: 6,
quantity: "2500",
tokenTicker: "ATOM" as TokenTicker,
},
gasLimit: "100000",
},
};
const expected = {
bytes: toUtf8(
'{"account_number":"0","chain_id":"cosmoshub-3","fee":{"amount":[{"amount":"2500","denom":"uatom"}],"gas":"100000"},"memo":"My first BASH payment","msgs":[{"type":"wasm/execute","value":{"contract":"cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd","msg":{"transfer":{"amount":"345","recipient":"cosmos1dddd"}},"sender":"cosmos1txqfn5jmcts0x0q7krdxj8tgf98tj0965vqlmq","sent_funds":[]}}],"sequence":"99"}',
),
prehashType: PrehashType.Sha256,
};
expect(codec.bytesToSign(bashSendTx, nonce)).toEqual(expected);
});
});
describe("bytesToPost", () => {

View File

@ -26,19 +26,25 @@ import { pubkeyToAddress } from "./address";
import { Caip5 } from "./caip5";
import { parseTx } from "./decode";
import { buildSignedTx, buildUnsignedTx } from "./encode";
import { BankTokens, nonceToAccountNumber, nonceToSequence } from "./types";
import { BankTokens, Erc20Token, nonceToAccountNumber, nonceToSequence } from "./types";
export class CosmWasmCodec implements TxCodec {
private readonly addressPrefix: CosmosAddressBech32Prefix;
private readonly tokens: BankTokens;
private readonly bankTokens: BankTokens;
private readonly erc20Tokens: readonly Erc20Token[];
public constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: BankTokens) {
public constructor(
addressPrefix: CosmosAddressBech32Prefix,
bankTokens: BankTokens,
erc20Tokens: readonly Erc20Token[] = [],
) {
this.addressPrefix = addressPrefix;
this.tokens = tokens;
this.bankTokens = bankTokens;
this.erc20Tokens = erc20Tokens;
}
public bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob {
const built = buildUnsignedTx(unsigned, this.tokens);
const built = buildUnsignedTx(unsigned, this.bankTokens, this.erc20Tokens);
const nonceInfo: types.NonceInfo = {
account_number: nonceToAccountNumber(nonce),
@ -61,7 +67,7 @@ export class CosmWasmCodec implements TxCodec {
// PostableBytes are JSON-encoded StdTx
public bytesToPost(signed: SignedTransaction): PostableBytes {
// TODO: change this as well (return StdTx, not AminoTx)?
const built = buildSignedTx(signed, this.tokens);
const built = buildSignedTx(signed, this.bankTokens, this.erc20Tokens);
return marshalTx(built.value) as PostableBytes;
}
@ -79,7 +85,7 @@ export class CosmWasmCodec implements TxCodec {
throw new Error("Nonce is required");
}
const parsed = unmarshalTx(bytes);
return parseTx(parsed, chainId, nonce, this.tokens);
return parseTx(parsed, chainId, nonce, this.bankTokens);
}
public identityToAddress(identity: Identity): Address {

View File

@ -11,11 +11,16 @@ import {
TxCodec,
UnsignedTransaction,
} from "@iov/bcp";
import { BankTokens } from "./types";
import { BankTokens, Erc20Token } from "./types";
export declare class CosmWasmCodec implements TxCodec {
private readonly addressPrefix;
private readonly tokens;
constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: BankTokens);
private readonly bankTokens;
private readonly erc20Tokens;
constructor(
addressPrefix: CosmosAddressBech32Prefix,
bankTokens: BankTokens,
erc20Tokens?: readonly Erc20Token[],
);
bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob;
bytesToPost(signed: SignedTransaction): PostableBytes;
identifier(_signed: SignedTransaction): TransactionId;