Add read support for ERC20 tokens
This commit is contained in:
parent
6e83bd6459
commit
df32bf6d95
@ -43,6 +43,7 @@
|
||||
"@iov/crypto": "^2.0.0-alpha.7",
|
||||
"@iov/encoding": "^2.0.0-alpha.7",
|
||||
"@iov/stream": "^2.0.0-alpha.7",
|
||||
"@iov/utils": "^2.0.0-alpha.7",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"readonly-date": "^1.0.0",
|
||||
"xstream": "^11.11.0"
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
import { Secp256k1 } from "@iov/crypto";
|
||||
import { Encoding } from "@iov/encoding";
|
||||
import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol";
|
||||
import { assert } from "@iov/utils";
|
||||
|
||||
import { CosmWasmCodec, cosmWasmCodec } from "./cosmwasmcodec";
|
||||
import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection";
|
||||
@ -33,21 +34,30 @@ describe("CosmWasmConnection", () => {
|
||||
const httpUrl = "http://localhost:1317";
|
||||
const defaultChainId = "cosmos:testing" as ChainId;
|
||||
const defaultEmptyAddress = "cosmos1h806c7khnvmjlywdrkdgk2vrayy2mmvf9rxk2r" as Address;
|
||||
const defaultAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6" as Address;
|
||||
const defaultPubkey = {
|
||||
algo: Algorithm.Secp256k1,
|
||||
data: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ") as PubkeyBytes,
|
||||
};
|
||||
const faucetMnemonic =
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone";
|
||||
const faucetPath = HdPaths.cosmos(0);
|
||||
const defaultRecipient = "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" as Address;
|
||||
const faucetAccount = {
|
||||
pubkey: {
|
||||
algo: Algorithm.Secp256k1,
|
||||
data: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ") as PubkeyBytes,
|
||||
},
|
||||
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6" as Address,
|
||||
};
|
||||
const unusedAccount = {
|
||||
pubkey: {
|
||||
algo: Algorithm.Secp256k1,
|
||||
data: fromBase64("ArkCaFUJ/IH+vKBmNRCdUVl3mCAhbopk9jjW4Ko4OfRQ") as PubkeyBytes,
|
||||
},
|
||||
address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u" as Address,
|
||||
};
|
||||
|
||||
const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix;
|
||||
|
||||
// this is for wasmd blockchain
|
||||
const defaultTokens: TokenConfiguration = {
|
||||
bank: [
|
||||
const defaultConfig: TokenConfiguration = {
|
||||
bankTokens: [
|
||||
{
|
||||
fractionalDigits: 6,
|
||||
name: "Fee Token",
|
||||
@ -61,12 +71,26 @@ describe("CosmWasmConnection", () => {
|
||||
denom: "ustake",
|
||||
},
|
||||
],
|
||||
erc20Tokens: [
|
||||
{
|
||||
contractAddress: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5",
|
||||
fractionalDigits: 5,
|
||||
ticker: "ASH",
|
||||
name: "Ash Token",
|
||||
},
|
||||
{
|
||||
contractAddress: "cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd",
|
||||
fractionalDigits: 0,
|
||||
ticker: "BASH",
|
||||
name: "Bash Token",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe("establish", () => {
|
||||
it("can connect to Cosmos via http", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
expect(connection).toBeTruthy();
|
||||
connection.disconnect();
|
||||
});
|
||||
@ -75,7 +99,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("chainId", () => {
|
||||
it("displays the chain ID", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const chainId = connection.chainId();
|
||||
expect(chainId).toEqual(defaultChainId);
|
||||
connection.disconnect();
|
||||
@ -85,7 +109,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("height", () => {
|
||||
it("displays the current height", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const height = await connection.height();
|
||||
expect(height).toBeGreaterThan(0);
|
||||
connection.disconnect();
|
||||
@ -95,7 +119,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("getToken", () => {
|
||||
it("displays a given token", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const token = await connection.getToken("COSM" as TokenTicker);
|
||||
expect(token).toEqual({
|
||||
fractionalDigits: 6,
|
||||
@ -107,7 +131,7 @@ describe("CosmWasmConnection", () => {
|
||||
|
||||
it("resolves to undefined if the token is not supported", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const token = await connection.getToken("whatever" as TokenTicker);
|
||||
expect(token).toBeUndefined();
|
||||
connection.disconnect();
|
||||
@ -117,10 +141,19 @@ describe("CosmWasmConnection", () => {
|
||||
describe("getAllTokens", () => {
|
||||
it("resolves to a list of all supported tokens", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const tokens = await connection.getAllTokens();
|
||||
// TODO: make this more flexible
|
||||
expect(tokens).toEqual([
|
||||
{
|
||||
fractionalDigits: 5,
|
||||
tokenName: "Ash Token",
|
||||
tokenTicker: "ASH" as TokenTicker,
|
||||
},
|
||||
{
|
||||
fractionalDigits: 0,
|
||||
tokenName: "Bash Token",
|
||||
tokenTicker: "BASH" as TokenTicker,
|
||||
},
|
||||
{
|
||||
fractionalDigits: 6,
|
||||
tokenName: "Fee Token",
|
||||
@ -139,7 +172,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("identifier", () => {
|
||||
it("calculates tx hash from PostableBytes", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const postable = cosmWasmCodec.bytesToPost(signedTxJson);
|
||||
const id = await connection.identifier(postable);
|
||||
expect(id).toMatch(/^[0-9A-F]{64}$/);
|
||||
@ -150,7 +183,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("getAccount", () => {
|
||||
it("gets an empty account by address", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const account = await connection.getAccount({ address: defaultEmptyAddress });
|
||||
expect(account).toBeUndefined();
|
||||
connection.disconnect();
|
||||
@ -158,35 +191,50 @@ describe("CosmWasmConnection", () => {
|
||||
|
||||
it("gets an account by address", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const account = await connection.getAccount({ address: defaultAddress });
|
||||
if (account === undefined) {
|
||||
throw new Error("Expected account not to be undefined");
|
||||
}
|
||||
expect(account.address).toEqual(defaultAddress);
|
||||
// Undefined until we sign a transaction (on multiple runs against one server this will be set), allow both
|
||||
if (account.pubkey !== undefined) {
|
||||
expect(account.pubkey).toEqual(defaultPubkey);
|
||||
}
|
||||
// Starts with two tokens
|
||||
expect(account.balance.length).toEqual(2);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const account = await connection.getAccount({ address: unusedAccount.address });
|
||||
assert(account, "Account must be defined");
|
||||
expect(account.address).toEqual(unusedAccount.address);
|
||||
expect(account.pubkey).toBeUndefined();
|
||||
expect(account.balance).toEqual([
|
||||
{
|
||||
tokenTicker: "ASH" as TokenTicker,
|
||||
quantity: "12812345",
|
||||
fractionalDigits: 5,
|
||||
},
|
||||
{
|
||||
tokenTicker: "BASH" as TokenTicker,
|
||||
quantity: "42",
|
||||
fractionalDigits: 0,
|
||||
},
|
||||
{
|
||||
tokenTicker: "COSM" as TokenTicker,
|
||||
quantity: "1000000000",
|
||||
fractionalDigits: 6,
|
||||
},
|
||||
{
|
||||
tokenTicker: "STAKE" as TokenTicker,
|
||||
quantity: "1000000000",
|
||||
fractionalDigits: 6,
|
||||
},
|
||||
]);
|
||||
connection.disconnect();
|
||||
});
|
||||
|
||||
it("gets an account by pubkey", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const account = await connection.getAccount({ pubkey: defaultPubkey });
|
||||
if (account === undefined) {
|
||||
throw new Error("Expected account not to be undefined");
|
||||
}
|
||||
expect(account.address).toEqual(defaultAddress);
|
||||
// Undefined until we sign a transaction (on multiple runs against one server this will be set), allow both
|
||||
if (account.pubkey !== undefined) {
|
||||
expect(account.pubkey).toEqual(defaultPubkey);
|
||||
}
|
||||
// Starts with two tokens
|
||||
expect(account.balance.length).toEqual(2);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const byAddress = await connection.getAccount({ address: unusedAccount.address });
|
||||
const byPubkey = await connection.getAccount({ pubkey: unusedAccount.pubkey });
|
||||
expect(byPubkey).toEqual(byAddress); // above we verified that by address works as expected
|
||||
connection.disconnect();
|
||||
});
|
||||
|
||||
it("has a pubkey when getting account with transactions", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const account = await connection.getAccount({ address: faucetAccount.address });
|
||||
expect(account?.pubkey).toEqual(faucetAccount.pubkey);
|
||||
connection.disconnect();
|
||||
});
|
||||
});
|
||||
@ -194,7 +242,7 @@ describe("CosmWasmConnection", () => {
|
||||
describe("integration tests", () => {
|
||||
it("can post and get a transaction", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const profile = new UserProfile();
|
||||
const wallet = profile.addWallet(Secp256k1HdWallet.fromMnemonic(faucetMnemonic));
|
||||
const faucet = await profile.createIdentity(wallet.id, defaultChainId, faucetPath);
|
||||
@ -214,7 +262,7 @@ describe("CosmWasmConnection", () => {
|
||||
});
|
||||
const nonce = await connection.getNonce({ address: faucetAddress });
|
||||
// TODO: we need to use custom codecs everywhere
|
||||
const codec = new CosmWasmCodec(defaultPrefix, defaultTokens.bank);
|
||||
const codec = new CosmWasmCodec(defaultPrefix, defaultConfig.bankTokens);
|
||||
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
||||
const postableBytes = codec.bytesToPost(signed);
|
||||
const response = await connection.postTx(postableBytes);
|
||||
@ -259,7 +307,7 @@ describe("CosmWasmConnection", () => {
|
||||
|
||||
it("can post and search for a transaction", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens);
|
||||
const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultConfig);
|
||||
const profile = new UserProfile();
|
||||
const wallet = profile.addWallet(Secp256k1HdWallet.fromMnemonic(faucetMnemonic));
|
||||
const faucet = await profile.createIdentity(wallet.id, defaultChainId, faucetPath);
|
||||
@ -279,7 +327,7 @@ describe("CosmWasmConnection", () => {
|
||||
});
|
||||
const nonce = await connection.getNonce({ address: faucetAddress });
|
||||
// TODO: we need to use custom codecs everywhere
|
||||
const codec = new CosmWasmCodec(defaultPrefix, defaultTokens.bank);
|
||||
const codec = new CosmWasmCodec(defaultPrefix, defaultConfig.bankTokens);
|
||||
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
|
||||
const postableBytes = codec.bytesToPost(signed);
|
||||
const response = await connection.postTx(postableBytes);
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
Account,
|
||||
AccountQuery,
|
||||
AddressQuery,
|
||||
Amount,
|
||||
BlockchainConnection,
|
||||
BlockHeader,
|
||||
BlockId,
|
||||
@ -37,7 +38,7 @@ import { Stream } from "xstream";
|
||||
import { decodeCosmosPubkey, pubkeyToAddress } from "./address";
|
||||
import { Caip5 } from "./caip5";
|
||||
import { decodeAmount, parseTxsResponse } from "./decode";
|
||||
import { accountToNonce, BankToken } from "./types";
|
||||
import { accountToNonce, BankToken, Erc20Token } from "./types";
|
||||
|
||||
const { toHex } = Encoding;
|
||||
|
||||
@ -71,7 +72,9 @@ function buildQueryString({
|
||||
|
||||
export interface TokenConfiguration {
|
||||
/** Supported tokens of the Cosmos SDK bank module */
|
||||
readonly bank: ReadonlyArray<BankToken & { readonly name: string }>;
|
||||
readonly bankTokens: ReadonlyArray<BankToken & { readonly name: string }>;
|
||||
/** Smart contract based tokens (ERC20 compatible). Unset means empty array. */
|
||||
readonly erc20Tokens?: ReadonlyArray<Erc20Token & { readonly name: string }>;
|
||||
}
|
||||
|
||||
export class CosmWasmConnection implements BlockchainConnection {
|
||||
@ -95,9 +98,10 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
private readonly chainData: ChainData;
|
||||
private readonly addressPrefix: CosmosAddressBech32Prefix;
|
||||
private readonly bankTokens: readonly BankToken[];
|
||||
private readonly erc20Tokens: readonly Erc20Token[];
|
||||
|
||||
// these are derived from arguments (cached for use in multiple functions)
|
||||
private readonly primaryToken: Token;
|
||||
private readonly feeToken: BankToken | undefined;
|
||||
private readonly supportedTokens: readonly Token[];
|
||||
|
||||
private constructor(
|
||||
@ -109,14 +113,17 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
this.restClient = restClient;
|
||||
this.chainData = chainData;
|
||||
this.addressPrefix = addressPrefix;
|
||||
this.bankTokens = tokens.bank;
|
||||
|
||||
this.supportedTokens = tokens.bank.map(info => ({
|
||||
tokenTicker: info.ticker as TokenTicker,
|
||||
tokenName: info.name,
|
||||
fractionalDigits: info.fractionalDigits,
|
||||
}));
|
||||
this.primaryToken = this.supportedTokens[0];
|
||||
this.bankTokens = tokens.bankTokens;
|
||||
this.feeToken = this.bankTokens.find(() => true);
|
||||
const erc20Tokens = tokens.erc20Tokens || [];
|
||||
this.erc20Tokens = erc20Tokens;
|
||||
this.supportedTokens = [...tokens.bankTokens, ...erc20Tokens]
|
||||
.map(info => ({
|
||||
tokenTicker: info.ticker as TokenTicker,
|
||||
tokenName: info.name,
|
||||
fractionalDigits: info.fractionalDigits,
|
||||
}))
|
||||
.sort((a, b) => a.tokenTicker.localeCompare(b.tokenTicker));
|
||||
}
|
||||
|
||||
public disconnect(): void {
|
||||
@ -154,14 +161,35 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
if (!account.address) {
|
||||
return undefined;
|
||||
}
|
||||
const supportedCoins = account.coins.filter(({ denom }) =>
|
||||
|
||||
const supportedBankCoins = account.coins.filter(({ denom }) =>
|
||||
this.bankTokens.find(token => token.denom === denom),
|
||||
);
|
||||
const erc20Amounts = await Promise.all(
|
||||
this.erc20Tokens.map(
|
||||
async (erc20): Promise<Amount> => {
|
||||
const queryMsg = { balance: { address: address } };
|
||||
const response = JSON.parse(
|
||||
await this.restClient.queryContractSmart(erc20.contractAddress, queryMsg),
|
||||
);
|
||||
return {
|
||||
fractionalDigits: erc20.fractionalDigits,
|
||||
quantity: response.balance,
|
||||
tokenTicker: erc20.ticker as TokenTicker,
|
||||
};
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
const balance = [
|
||||
...supportedBankCoins.map(coin => decodeAmount(this.bankTokens, coin)),
|
||||
...erc20Amounts,
|
||||
].sort((a, b) => a.tokenTicker.localeCompare(b.tokenTicker));
|
||||
|
||||
const pubkey = !account.public_key ? undefined : decodeCosmosPubkey(account.public_key);
|
||||
return {
|
||||
address: address,
|
||||
balance: supportedCoins.map(coin => decodeAmount(this.bankTokens, coin)),
|
||||
balance: balance,
|
||||
pubkey: pubkey,
|
||||
};
|
||||
}
|
||||
@ -283,11 +311,12 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
if (!isSendTransaction(tx)) {
|
||||
throw new Error("Received transaction of unsupported kind.");
|
||||
}
|
||||
if (!this.feeToken) throw new Error("This connection has no fee token configured.");
|
||||
return {
|
||||
tokens: {
|
||||
fractionalDigits: this.primaryToken.fractionalDigits,
|
||||
fractionalDigits: this.feeToken.fractionalDigits,
|
||||
quantity: "5000",
|
||||
tokenTicker: this.primaryToken.tokenTicker,
|
||||
tokenTicker: this.feeToken.ticker as TokenTicker,
|
||||
},
|
||||
gasLimit: "200000",
|
||||
};
|
||||
|
||||
@ -13,7 +13,7 @@ export function createCosmWasmConnector(
|
||||
tokens: TokenConfiguration,
|
||||
expectedChainId?: ChainId,
|
||||
): ChainConnector<CosmWasmConnection> {
|
||||
const codec = new CosmWasmCodec(addressPrefix, tokens.bank);
|
||||
const codec = new CosmWasmCodec(addressPrefix, tokens.bankTokens);
|
||||
return {
|
||||
establishConnection: async () => CosmWasmConnection.establish(url, addressPrefix, tokens),
|
||||
codec: codec,
|
||||
|
||||
@ -18,6 +18,21 @@ export interface BankToken {
|
||||
|
||||
export type BankTokens = ReadonlyArray<BankToken>;
|
||||
|
||||
export interface Erc20Token {
|
||||
readonly contractAddress: 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;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
const maxAcct = 1 << 23;
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
|
||||
4
packages/bcp/types/cosmwasmcodec.d.ts
vendored
4
packages/bcp/types/cosmwasmcodec.d.ts
vendored
@ -11,11 +11,11 @@ import {
|
||||
TxCodec,
|
||||
UnsignedTransaction,
|
||||
} from "@iov/bcp";
|
||||
import { TokenInfos } from "./types";
|
||||
import { BankTokens } from "./types";
|
||||
export declare class CosmWasmCodec implements TxCodec {
|
||||
private readonly addressPrefix;
|
||||
private readonly tokens;
|
||||
constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos);
|
||||
constructor(addressPrefix: CosmosAddressBech32Prefix, tokens: BankTokens);
|
||||
bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob;
|
||||
bytesToPost(signed: SignedTransaction): PostableBytes;
|
||||
identifier(_signed: SignedTransaction): TransactionId;
|
||||
|
||||
15
packages/bcp/types/cosmwasmconnection.d.ts
vendored
15
packages/bcp/types/cosmwasmconnection.d.ts
vendored
@ -21,11 +21,17 @@ import {
|
||||
UnsignedTransaction,
|
||||
} from "@iov/bcp";
|
||||
import { Stream } from "xstream";
|
||||
import { TokenInfo } from "./types";
|
||||
import { BankToken, Erc20Token } from "./types";
|
||||
export interface TokenConfiguration {
|
||||
/** Supported tokens of the Cosmos SDK bank module */
|
||||
readonly bank: ReadonlyArray<
|
||||
TokenInfo & {
|
||||
readonly bankTokens: ReadonlyArray<
|
||||
BankToken & {
|
||||
readonly name: string;
|
||||
}
|
||||
>;
|
||||
/** Smart contract based tokens (ERC20 compatible). Unset means empty array. */
|
||||
readonly erc20Tokens?: ReadonlyArray<
|
||||
Erc20Token & {
|
||||
readonly name: string;
|
||||
}
|
||||
>;
|
||||
@ -41,7 +47,8 @@ export declare class CosmWasmConnection implements BlockchainConnection {
|
||||
private readonly chainData;
|
||||
private readonly addressPrefix;
|
||||
private readonly bankTokens;
|
||||
private readonly primaryToken;
|
||||
private readonly erc20Tokens;
|
||||
private readonly feeToken;
|
||||
private readonly supportedTokens;
|
||||
private constructor();
|
||||
disconnect(): void;
|
||||
|
||||
14
packages/bcp/types/decode.d.ts
vendored
14
packages/bcp/types/decode.d.ts
vendored
@ -12,24 +12,24 @@ import {
|
||||
UnsignedTransaction,
|
||||
} from "@iov/bcp";
|
||||
import { Decimal } from "@iov/encoding";
|
||||
import { TokenInfos } from "./types";
|
||||
import { BankTokens } 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): UnsignedTransaction;
|
||||
export declare function parseFee(fee: types.StdFee, tokens: TokenInfos): Fee;
|
||||
export declare function coinToDecimal(tokens: BankTokens, coin: types.Coin): readonly [Decimal, string];
|
||||
export declare function decodeAmount(tokens: BankTokens, coin: types.Coin): Amount;
|
||||
export declare function parseMsg(msg: types.Msg, chainId: ChainId, tokens: BankTokens): UnsignedTransaction;
|
||||
export declare function parseFee(fee: types.StdFee, tokens: BankTokens): Fee;
|
||||
export declare function parseTx(
|
||||
txValue: types.StdTx,
|
||||
chainId: ChainId,
|
||||
nonce: Nonce,
|
||||
tokens: TokenInfos,
|
||||
tokens: BankTokens,
|
||||
): SignedTransaction;
|
||||
export declare function parseTxsResponse(
|
||||
chainId: ChainId,
|
||||
currentHeight: number,
|
||||
nonce: Nonce,
|
||||
response: TxsResponse,
|
||||
tokens: TokenInfos,
|
||||
tokens: BankTokens,
|
||||
): ConfirmedAndSignedTransaction<UnsignedTransaction>;
|
||||
|
||||
12
packages/bcp/types/encode.d.ts
vendored
12
packages/bcp/types/encode.d.ts
vendored
@ -1,11 +1,11 @@
|
||||
import { types } from "@cosmwasm/sdk";
|
||||
import { Amount, Fee, FullSignature, PubkeyBundle, SignedTransaction, UnsignedTransaction } from "@iov/bcp";
|
||||
import { Decimal } from "@iov/encoding";
|
||||
import { TokenInfos } from "./types";
|
||||
import { BankTokens } 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 decimalToCoin(lookup: BankTokens, value: Decimal, ticker: string): types.Coin;
|
||||
export declare function encodeAmount(amount: Amount, tokens: BankTokens): types.Coin;
|
||||
export declare function encodeFee(fee: Fee, tokens: BankTokens): types.StdFee;
|
||||
export declare function encodeFullSignature(fullSignature: FullSignature): types.StdSignature;
|
||||
export declare function buildUnsignedTx(tx: UnsignedTransaction, tokens: TokenInfos): types.AminoTx;
|
||||
export declare function buildSignedTx(tx: SignedTransaction, tokens: TokenInfos): types.AminoTx;
|
||||
export declare function buildUnsignedTx(tx: UnsignedTransaction, tokens: BankTokens): types.AminoTx;
|
||||
export declare function buildSignedTx(tx: SignedTransaction, tokens: BankTokens): types.AminoTx;
|
||||
|
||||
18
packages/bcp/types/types.d.ts
vendored
18
packages/bcp/types/types.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
import { types } from "@cosmwasm/sdk";
|
||||
import { Nonce } from "@iov/bcp";
|
||||
export interface TokenInfo {
|
||||
export interface BankToken {
|
||||
readonly denom: string;
|
||||
readonly ticker: string;
|
||||
/**
|
||||
@ -14,7 +14,21 @@ export interface TokenInfo {
|
||||
*/
|
||||
readonly fractionalDigits: number;
|
||||
}
|
||||
export declare type TokenInfos = ReadonlyArray<TokenInfo>;
|
||||
export declare type BankTokens = ReadonlyArray<BankToken>;
|
||||
export interface Erc20Token {
|
||||
readonly contractAddress: 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 function accountToNonce({ account_number: account, sequence }: types.NonceInfo): Nonce;
|
||||
export declare function nonceToAccountNumber(nonce: Nonce): number;
|
||||
export declare function nonceToSequence(nonce: Nonce): number;
|
||||
|
||||
@ -83,7 +83,9 @@ You should get output matching the following:
|
||||
|
||||
1. Faucet<br>
|
||||
economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone<br>
|
||||
A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ<br>
|
||||
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
|
||||
2. Unused: for testing account state; this account never changes balances or nonces<br>
|
||||
oyster design unusual machine spread century engine gravity focus cave carry slot<br>
|
||||
ArkCaFUJ/IH+vKBmNRCdUVl3mCAhbopk9jjW4Ko4OfRQ<br>
|
||||
cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u
|
||||
|
||||
Loading…
Reference in New Issue
Block a user