diff --git a/packages/faucet/package.json b/packages/faucet/package.json index c0a29a5a..5b1c1c89 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -36,7 +36,7 @@ "test-node": "node jasmine-testrunner.js", "test": "yarn build-or-skip && yarn test-node", "coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet", - "start-dev": "FAUCET_CREDIT_AMOUNT_UCOSM=10000000 FAUCET_CREDIT_AMOUNT_USTAKE=5000000 FAUCET_CONCURRENCY=3 FAUCET_MNEMONIC=\"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone\" ./bin/cosmos-faucet start \"http://localhost:1317\"", + "start-dev": "FAUCET_CREDIT_AMOUNT_UCOSM=10000000 FAUCET_CREDIT_AMOUNT_USTAKE=100000 FAUCET_CONCURRENCY=3 FAUCET_MNEMONIC=\"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone\" ./bin/cosmos-faucet start \"http://localhost:26657\"", "start-coralnet": "FAUCET_ADDRESS_PREFIX=coral FAUCET_TOKENS=\"ushell,ureef\" FAUCET_CREDIT_AMOUNT_USHELL=10000000 FAUCET_CREDIT_AMOUNT_UREEF=2000000 FAUCET_CONCURRENCY=3 FAUCET_MNEMONIC=\"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone\" ./bin/cosmos-faucet start \"https://lcd.coralnet.cosmwasm.com\"" }, "dependencies": { @@ -44,6 +44,8 @@ "@cosmjs/encoding": "^0.23.1", "@cosmjs/launchpad": "^0.23.1", "@cosmjs/math": "^0.23.1", + "@cosmjs/proto-signing": "^0.23.1", + "@cosmjs/stargate": "^0.23.1", "@cosmjs/utils": "^0.23.1", "@koa/cors": "^3.0.0", "koa": "^2.11.0", diff --git a/packages/faucet/src/actions/start.ts b/packages/faucet/src/actions/start.ts index f271d097..6d0d6e6e 100644 --- a/packages/faucet/src/actions/start.ts +++ b/packages/faucet/src/actions/start.ts @@ -1,4 +1,5 @@ import { CosmosClient } from "@cosmjs/launchpad"; +import { StargateClient } from "@cosmjs/stargate"; import { Webserver } from "../api/webserver"; import * as constants from "../constants"; @@ -15,18 +16,27 @@ export async function start(args: readonly string[]): Promise { // Connection const blockchainBaseUrl = args[0]; console.info(`Connecting to blockchain ${blockchainBaseUrl} ...`); - const chainId = await new CosmosClient(blockchainBaseUrl).getChainId(); + let chainId; + let stargate = true; + try { + chainId = await (await StargateClient.connect(blockchainBaseUrl)).getChainId(); + } catch (_error) { + chainId = await new CosmosClient(blockchainBaseUrl).getChainId(); + stargate = false; + } console.info(`Connected to network: ${chainId}`); // Faucet if (!constants.mnemonic) throw new Error("The FAUCET_MNEMONIC environment variable is not set"); + const logging = true; const faucet = await Faucet.make( blockchainBaseUrl, constants.addressPrefix, constants.tokenConfig, constants.mnemonic, constants.concurrency, - true, + stargate, + logging, ); const chainTokens = faucet.configuredTokens(); console.info("Chain tokens:", chainTokens); diff --git a/packages/faucet/src/faucet.spec.ts b/packages/faucet/src/faucet.spec.ts index 20558f00..dac80440 100644 --- a/packages/faucet/src/faucet.spec.ts +++ b/packages/faucet/src/faucet.spec.ts @@ -1,6 +1,7 @@ import { Random } from "@cosmjs/crypto"; import { Bech32 } from "@cosmjs/encoding"; import { CosmosClient } from "@cosmjs/launchpad"; +import { StargateClient } from "@cosmjs/stargate"; import { assert } from "@cosmjs/utils"; import { Faucet } from "./faucet"; @@ -12,7 +13,12 @@ function pendingWithoutWasmd(): void { } } -const httpUrl = "http://localhost:1317"; +function pendingWithoutSimapp(): void { + if (!process.env.SIMAPP_ENABLED) { + return pending("Set SIMAPP_ENABLED to enabled Stargate node-based tests"); + } +} + const defaultTokenConfig: TokenConfiguration = { bankTokens: ["ucosm", "ustake"], }; @@ -26,143 +32,433 @@ 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"; describe("Faucet", () => { - describe("constructor", () => { - it("can be constructed", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - expect(faucet).toBeTruthy(); - }); - }); + describe("launchpad", () => { + const apiUrl = "http://localhost:1317"; + const stargate = false; - describe("availableTokens", () => { - it("is empty when no tokens are configured", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, { bankTokens: [] }, faucetMnemonic, 3); - const tickers = await faucet.availableTokens(); - expect(tickers).toEqual([]); + describe("constructor", () => { + it("can be constructed", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + expect(faucet).toBeTruthy(); + }); }); - it("is not empty with default token config", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - const tickers = await faucet.availableTokens(); - expect(tickers).toEqual(["ucosm", "ustake"]); - }); - }); - - describe("send", () => { - it("can send bank token", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - const recipient = makeRandomAddress(); - await faucet.send({ - amount: { - amount: "23456", - denom: "ucosm", - }, - sender: faucet.holderAddress, - recipient: recipient, + describe("availableTokens", () => { + it("is empty when no tokens are configured", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + { bankTokens: [] }, + faucetMnemonic, + 3, + stargate, + ); + const tickers = await faucet.availableTokens(); + expect(tickers).toEqual([]); }); - const readOnlyClient = new CosmosClient(httpUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "23456", - denom: "ucosm", - }, - ]); + it("is not empty with default token config", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const tickers = await faucet.availableTokens(); + expect(tickers).toEqual(["ucosm", "ustake"]); + }); + }); + + describe("send", () => { + it("can send bank token", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.send({ + amount: { + amount: "23456", + denom: "ucosm", + }, + sender: faucet.holderAddress, + recipient: recipient, + }); + + const readOnlyClient = new CosmosClient(apiUrl); + const account = await readOnlyClient.getAccount(recipient); + assert(account); + expect(account.balance).toEqual([ + { + amount: "23456", + denom: "ucosm", + }, + ]); + }); + }); + + describe("refill", () => { + it("works", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + await faucet.refill(); + const readOnlyClient = new CosmosClient(apiUrl); + const distributorBalance = (await readOnlyClient.getAccount(faucet.distributorAddresses[0]))?.balance; + assert(distributorBalance); + expect(distributorBalance).toEqual([ + jasmine.objectContaining({ + denom: "ucosm", + }), + jasmine.objectContaining({ + denom: "ustake", + }), + ]); + expect(Number.parseInt(distributorBalance[0].amount, 10)).toBeGreaterThanOrEqual(80_000000); + expect(Number.parseInt(distributorBalance[1].amount, 10)).toBeGreaterThanOrEqual(80_000000); + }); + }); + + describe("credit", () => { + it("works for fee token", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.credit(recipient, "ucosm"); + + const readOnlyClient = new CosmosClient(apiUrl); + const account = await readOnlyClient.getAccount(recipient); + assert(account); + expect(account.balance).toEqual([ + { + amount: "10000000", + denom: "ucosm", + }, + ]); + }); + + it("works for stake token", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.credit(recipient, "ustake"); + + const readOnlyClient = new CosmosClient(apiUrl); + const account = await readOnlyClient.getAccount(recipient); + assert(account); + expect(account.balance).toEqual([ + { + amount: "10000000", + denom: "ustake", + }, + ]); + }); + }); + + describe("configuredTokens", () => { + it("works", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const tickers = faucet.configuredTokens(); + expect(tickers).toEqual(["ucosm", "ustake"]); + }); + }); + + describe("loadAccounts", () => { + it("works", async () => { + pendingWithoutWasmd(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 1, + stargate, + ); + const accounts = await faucet.loadAccounts(); + + const readOnlyClient = new CosmosClient(apiUrl); + const expectedHolderAccount = await readOnlyClient.getAccount(faucet.holderAddress); + const expectedDistributorAccount = await readOnlyClient.getAccount(faucet.distributorAddresses[0]); + assert(expectedHolderAccount); + assert(expectedDistributorAccount); + expect(accounts).toEqual([ + jasmine.objectContaining({ + address: expectedHolderAccount.address, + balance: expectedHolderAccount.balance, + }), + jasmine.objectContaining({ + address: expectedDistributorAccount.address, + balance: expectedDistributorAccount.balance, + }), + ]); + }); }); }); - describe("refill", () => { - it("works", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - await faucet.refill(); - const readOnlyClient = new CosmosClient(httpUrl); - const distributorBalance = (await readOnlyClient.getAccount(faucet.distributorAddresses[0]))?.balance; - assert(distributorBalance); - expect(distributorBalance).toEqual([ - jasmine.objectContaining({ - denom: "ucosm", - }), - jasmine.objectContaining({ - denom: "ustake", - }), - ]); - expect(Number.parseInt(distributorBalance[0].amount, 10)).toBeGreaterThanOrEqual(80_000000); - expect(Number.parseInt(distributorBalance[1].amount, 10)).toBeGreaterThanOrEqual(80_000000); - }); - }); + describe("stargate", () => { + const apiUrl = "localhost:26657"; + const stargate = true; + let originalEnvVariable: string | undefined; - describe("credit", () => { - it("works for fee token", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - const recipient = makeRandomAddress(); - await faucet.credit(recipient, "ucosm"); - - const readOnlyClient = new CosmosClient(httpUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "10000000", - denom: "ucosm", - }, - ]); + beforeAll(() => { + originalEnvVariable = process.env.FAUCET_CREDIT_AMOUNT_USTAKE; + process.env.FAUCET_CREDIT_AMOUNT_USTAKE = "100000"; }); - it("works for stake token", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - const recipient = makeRandomAddress(); - await faucet.credit(recipient, "ustake"); - - const readOnlyClient = new CosmosClient(httpUrl); - const account = await readOnlyClient.getAccount(recipient); - assert(account); - expect(account.balance).toEqual([ - { - amount: "10000000", - denom: "ustake", - }, - ]); + afterAll(() => { + process.env.FAUCET_CREDIT_AMOUNT_USTAKE = originalEnvVariable; }); - }); - describe("configuredTokens", () => { - it("works", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 3); - const tickers = faucet.configuredTokens(); - expect(tickers).toEqual(["ucosm", "ustake"]); + describe("constructor", () => { + it("can be constructed", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + expect(faucet).toBeTruthy(); + }); }); - }); - describe("loadAccounts", () => { - it("works", async () => { - pendingWithoutWasmd(); - const faucet = await Faucet.make(httpUrl, defaultAddressPrefix, defaultTokenConfig, faucetMnemonic, 1); - const accounts = await faucet.loadAccounts(); + describe("availableTokens", () => { + it("is empty when no tokens are configured", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + { bankTokens: [] }, + faucetMnemonic, + 3, + stargate, + ); + const tickers = await faucet.availableTokens(); + expect(tickers).toEqual([]); + }); - const readOnlyClient = new CosmosClient(httpUrl); - const expectedHolderAccount = await readOnlyClient.getAccount(faucet.holderAddress); - const expectedDistributorAccount = await readOnlyClient.getAccount(faucet.distributorAddresses[0]); - assert(expectedHolderAccount); - assert(expectedDistributorAccount); - expect(accounts).toEqual([ - jasmine.objectContaining({ - address: expectedHolderAccount.address, - balance: expectedHolderAccount.balance, - }), - jasmine.objectContaining({ - address: expectedDistributorAccount.address, - balance: expectedDistributorAccount.balance, - }), - ]); + it("is not empty with default token config", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const tickers = await faucet.availableTokens(); + expect(tickers).toEqual(["ucosm", "ustake"]); + }); + }); + + describe("send", () => { + it("can send bank token", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.send({ + amount: { + amount: "23456", + denom: "ucosm", + }, + sender: faucet.holderAddress, + recipient: recipient, + }); + + const readOnlyClient = await StargateClient.connect(apiUrl); + const account = await readOnlyClient.getAllBalancesUnverified(recipient); + assert(account); + expect(account).toEqual([ + { + amount: "23456", + denom: "ucosm", + }, + ]); + }); + }); + + describe("refill", () => { + it("works", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + await faucet.refill(); + const readOnlyClient = await StargateClient.connect(apiUrl); + const distributorBalance = await readOnlyClient.getAllBalancesUnverified( + faucet.distributorAddresses[0], + ); + assert(distributorBalance); + expect(distributorBalance).toEqual([ + jasmine.objectContaining({ + denom: "ucosm", + }), + jasmine.objectContaining({ + denom: "ustake", + }), + ]); + expect(Number.parseInt(distributorBalance[0].amount, 10)).toBeGreaterThanOrEqual(80_000000); + expect(Number.parseInt(distributorBalance[1].amount, 10)).toBeGreaterThanOrEqual(800000); + }); + }); + + describe("credit", () => { + it("works for fee token", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.credit(recipient, "ucosm"); + + const readOnlyClient = await StargateClient.connect(apiUrl); + const balance = await readOnlyClient.getAllBalancesUnverified(recipient); + assert(balance); + expect(balance).toEqual([ + { + amount: "10000000", + denom: "ucosm", + }, + ]); + }); + + it("works for stake token", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const recipient = makeRandomAddress(); + await faucet.credit(recipient, "ustake"); + + const readOnlyClient = await StargateClient.connect(apiUrl); + const balance = await readOnlyClient.getAllBalancesUnverified(recipient); + assert(balance); + expect(balance).toEqual([ + { + amount: "100000", + denom: "ustake", + }, + ]); + }); + }); + + describe("configuredTokens", () => { + it("works", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 3, + stargate, + ); + const tickers = faucet.configuredTokens(); + expect(tickers).toEqual(["ucosm", "ustake"]); + }); + }); + + describe("loadAccounts", () => { + it("works", async () => { + pendingWithoutSimapp(); + const faucet = await Faucet.make( + apiUrl, + defaultAddressPrefix, + defaultTokenConfig, + faucetMnemonic, + 1, + stargate, + ); + const accounts = await faucet.loadAccounts(); + + const readOnlyClient = await StargateClient.connect(apiUrl); + const expectedHolderBalance = await readOnlyClient.getAllBalancesUnverified(faucet.holderAddress); + const expectedDistributorBalance = await readOnlyClient.getAllBalancesUnverified( + faucet.distributorAddresses[0], + ); + assert(expectedHolderBalance); + assert(expectedDistributorBalance); + expect(accounts).toEqual([ + jasmine.objectContaining({ + address: faucet.holderAddress, + balance: expectedHolderBalance, + }), + jasmine.objectContaining({ + address: faucet.distributorAddresses[0], + balance: expectedDistributorBalance, + }), + ]); + }); }); }); }); diff --git a/packages/faucet/src/faucet.ts b/packages/faucet/src/faucet.ts index d6a8846a..c61a9890 100644 --- a/packages/faucet/src/faucet.ts +++ b/packages/faucet/src/faucet.ts @@ -1,14 +1,18 @@ import { - assertIsBroadcastTxSuccess, + assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessLaunchpad, CosmosClient, - OfflineSigner, SigningCosmosClient, } from "@cosmjs/launchpad"; +import { + assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessStargate, + SigningStargateClient, + StargateClient, +} from "@cosmjs/stargate"; import { sleep } from "@cosmjs/utils"; import * as constants from "./constants"; import { debugAccount, logAccountsState, logSendJob } from "./debugging"; -import { createWallets } from "./profile"; +import { createClients, createWallets } from "./profile"; import { TokenConfiguration, TokenManager } from "./tokenmanager"; import { MinimalAccount, SendJob } from "./types"; @@ -23,10 +27,13 @@ export class Faucet { config: TokenConfiguration, mnemonic: string, numberOfDistributors: number, + stargate = true, logging = false, ): Promise { - const wallets = await createWallets(mnemonic, addressPrefix, numberOfDistributors, logging); - return new Faucet(apiUrl, addressPrefix, config, wallets, logging); + const wallets = await createWallets(mnemonic, addressPrefix, numberOfDistributors, stargate, logging); + const clients = await createClients(apiUrl, wallets); + const readonlyClient = stargate ? await StargateClient.connect(apiUrl) : new CosmosClient(apiUrl); + return new Faucet(addressPrefix, config, clients, readonlyClient, logging); } public readonly addressPrefix: string; @@ -35,39 +42,28 @@ export class Faucet { private readonly tokenConfig: TokenConfiguration; private readonly tokenManager: TokenManager; - private readonly readOnlyClient: CosmosClient; - private readonly clients: { [senderAddress: string]: SigningCosmosClient }; + private readonly readOnlyClient: CosmosClient | StargateClient; + private readonly clients: { [senderAddress: string]: SigningCosmosClient | SigningStargateClient }; private readonly logging: boolean; private creditCount = 0; private constructor( - apiUrl: string, addressPrefix: string, config: TokenConfiguration, - wallets: ReadonlyArray, + clients: ReadonlyArray, + readonlyClient: CosmosClient | StargateClient, logging = false, ) { this.addressPrefix = addressPrefix; this.tokenConfig = config; this.tokenManager = new TokenManager(config); - this.readOnlyClient = new CosmosClient(apiUrl); - - this.holderAddress = wallets[0][0]; - this.distributorAddresses = wallets.slice(1).map((pair) => pair[0]); - - // we need one client per sender - const clients: { [senderAddress: string]: SigningCosmosClient } = {}; - for (const [senderAddress, wallet] of wallets) { - clients[senderAddress] = new SigningCosmosClient( - apiUrl, - senderAddress, - wallet, - constants.gasPrice, - constants.gasLimits, - ); - } - this.clients = clients; + this.readOnlyClient = readonlyClient; + [this.holderAddress, ...this.distributorAddresses] = clients.map(([address]) => address); + this.clients = clients.reduce( + (acc, [senderAddress, client]) => ({ ...acc, [senderAddress]: client }), + {}, + ); this.logging = logging; } @@ -75,9 +71,7 @@ export class Faucet { * Returns a list of denoms of tokens owned by the the holder and configured in the faucet */ public async availableTokens(): Promise { - const holderAccount = await this.readOnlyClient.getAccount(this.holderAddress); - const balance = holderAccount ? holderAccount.balance : []; - + const { balance } = await this.loadAccount(this.holderAddress); return balance .filter((b) => b.amount !== "0") .map((b) => this.tokenConfig.bankTokens.find((token) => token == b.denom)) @@ -89,8 +83,13 @@ export class Faucet { * Throws an error if the transaction failed. */ public async send(job: SendJob): Promise { - const result = await this.clients[job.sender].sendTokens(job.recipient, [job.amount], constants.memo); - assertIsBroadcastTxSuccess(result); + const client = this.clients[job.sender]; + if (client instanceof SigningCosmosClient) { + const result = await client.sendTokens(job.recipient, [job.amount], constants.memo); + return assertIsBroadcastTxSuccessLaunchpad(result); + } + const result = await client.sendTokens(job.sender, job.recipient, [job.amount], constants.memo); + assertIsBroadcastTxSuccessStargate(result); } /** Use one of the distributor accounts to send tokens to user */ @@ -111,24 +110,21 @@ export class Faucet { return Array.from(this.tokenConfig.bankTokens); } + public async loadAccount(address: string): Promise { + const balance = + this.readOnlyClient instanceof CosmosClient + ? (await this.readOnlyClient.getAccount(address))?.balance ?? [] + : await this.readOnlyClient.getAllBalancesUnverified(address); + + return { + address: address, + balance: balance, + }; + } + public async loadAccounts(): Promise { const addresses = [this.holderAddress, ...this.distributorAddresses]; - - return Promise.all( - addresses.map( - async (address): Promise => { - const response = await this.readOnlyClient.getAccount(address); - if (response) { - return response; - } else { - return { - address: address, - balance: [], - }; - } - }, - ), - ); + return Promise.all(addresses.map(this.loadAccount.bind(this))); } public async refill(): Promise { diff --git a/packages/faucet/src/profile.ts b/packages/faucet/src/profile.ts index 39d9ec05..2dacc568 100644 --- a/packages/faucet/src/profile.ts +++ b/packages/faucet/src/profile.ts @@ -1,19 +1,25 @@ import { pathToString } from "@cosmjs/crypto"; -import { makeCosmoshubPath, OfflineSigner, Secp256k1HdWallet } from "@cosmjs/launchpad"; +import { makeCosmoshubPath, Secp256k1HdWallet, SigningCosmosClient } from "@cosmjs/launchpad"; +import { DirectSecp256k1Wallet, isOfflineDirectSigner, OfflineSigner } from "@cosmjs/proto-signing"; +import { SigningStargateClient } from "@cosmjs/stargate"; + +import * as constants from "./constants"; export async function createWallets( mnemonic: string, addressPrefix: string, numberOfDistributors: number, + stargate = true, logging = false, ): Promise> { + const createWallet = stargate ? DirectSecp256k1Wallet.fromMnemonic : Secp256k1HdWallet.fromMnemonic; const wallets = new Array(); // first account is the token holder const numberOfIdentities = 1 + numberOfDistributors; for (let i = 0; i < numberOfIdentities; i++) { const path = makeCosmoshubPath(i); - const wallet = await Secp256k1HdWallet.fromMnemonic(mnemonic, path, addressPrefix); + const wallet = await createWallet(mnemonic, path, addressPrefix); const [{ address }] = await wallet.getAccounts(); if (logging) { const role = i === 0 ? "token holder " : `distributor ${i}`; @@ -24,3 +30,22 @@ export async function createWallets( return wallets; } + +export async function createClients( + apiUrl: string, + wallets: ReadonlyArray, +): Promise> { + // we need one client per sender + return Promise.all( + wallets.map( + async ([senderAddress, wallet]): Promise< + readonly [string, SigningCosmosClient | SigningStargateClient] + > => [ + senderAddress, + isOfflineDirectSigner(wallet) + ? await SigningStargateClient.connectWithWallet(apiUrl, wallet, {}) + : new SigningCosmosClient(apiUrl, senderAddress, wallet, constants.gasPrice, constants.gasLimits), + ], + ), + ); +} diff --git a/packages/stargate/src/index.ts b/packages/stargate/src/index.ts index abb21525..3fabcd9f 100644 --- a/packages/stargate/src/index.ts +++ b/packages/stargate/src/index.ts @@ -1 +1,2 @@ -export { StargateClient } from "./stargateclient"; +export { assertIsBroadcastTxSuccess, StargateClient } from "./stargateclient"; +export { SigningStargateClient } from "./signingstargateclient"; diff --git a/packages/stargate/types/index.d.ts b/packages/stargate/types/index.d.ts index abb21525..3fabcd9f 100644 --- a/packages/stargate/types/index.d.ts +++ b/packages/stargate/types/index.d.ts @@ -1 +1,2 @@ -export { StargateClient } from "./stargateclient"; +export { assertIsBroadcastTxSuccess, StargateClient } from "./stargateclient"; +export { SigningStargateClient } from "./signingstargateclient";