Skip to content

Commit

Permalink
refactor: add pollTx back to wallet
Browse files Browse the repository at this point in the history
* also renamed `broadcastTxWithFeeEstimation` to `broadcastTxSync`
  • Loading branch information
AaronCQL committed Oct 17, 2023
1 parent 0b13831 commit 1fcc8c9
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 28 deletions.
11 changes: 5 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# Changelog

## `v0.0.37` [breaking change]
## `v0.0.38` [breaking change]

### Features

- Added `MnemonicWallet` to allow programmatic signing and broadcasting of txs without relying on a 3rd party wallet/signer (see examples directory)
- Simplified wallet APIs **[breaking change]**
- `getAccount()`: reworked to `getAuthInfo()`, but consumers are no longer required to call this method to broadcast transactions
- `pollTx()`: removed and combined with `broadcastTx()`
- `estimateFee()`: second parameter now accepts the `feeMultiplier` directly (still optional)
- `broadcastTx()`: second parameter now accepts the `fee` from the result of `estimateFee()` (no longer optional)
- `broadcastTxWithFeeEstimation()`: newly added function that combines `estimateFee` and `broadcastTx`
- `getAccount()`: renamed and reworked to `getAuthInfo()`, but consumers are no longer required to call this method to broadcast transactions
- `estimateFee()`: second parameter now accepts the `feeMultiplier` directly (still optional) instead of the auth info
- `broadcastTx()`: second parameter now accepts the `fee` from the result of `estimateFee()` (no longer optional) instead of the auth info
- `broadcastTxSync()`: new function that executes `estimateFee`, `broadcastTx`, and `pollTx` sequentially
- Handle account sequence mismatch errors directly in `ConnectedWallet.estimateFee()` by retrying once with the correct sequence

### Miscellaneous
Expand Down
2 changes: 1 addition & 1 deletion examples/mnemonic-wallet/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async function main() {
console.log("Signature:", signature);

// Broadcast a transaction
// const res = await wallet.broadcastTxWithFeeEstimation({ ... });
// const res = await wallet.broadcastTxSync( ... );
// console.log("Tx result:", res);
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cosmes",
"version": "0.0.37",
"version": "0.0.38",
"private": false,
"packageManager": "pnpm@8.3.0",
"sideEffects": false,
Expand Down
54 changes: 35 additions & 19 deletions src/wallet/wallets/ConnectedWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,22 +144,18 @@ export abstract class ConnectedWallet {
}

/**
* Signs and broadcasts the given `unsignedTx` and returns the result of the tx.
* Signs and broadcasts the given `unsignedTx`, returning the tx hash if successful.
* The `fee` parameter can (and should) be obtained by running `estimateFee` on
* the `unsignedTx` prior to calling this method.
*
* - The `fee` parameter can (and should) be obtained by running `estimateFee` on
* the `unsignedTx` prior to calling this method
* - The tx result will be polled every `intervalSeconds` until it is included in
* a block or when `maxAttempts` is reached (default: 2 seconds, 64 attempts)
* **Important**: successful execution of this method does not guarantee that the
* tx was successfully included in a block. Use `pollTx` to poll for the result of
* the tx.
*
* @throws if the user denies the signing of the tx.
* @throws if the tx fails to broadcast.
* @throws if the tx does not have a response.
* @throws if the tx is not found after the given number of `maxAttempts`.
*/
public async broadcastTx(
unsignedTx: UnsignedTx,
fee: Fee,
{ maxAttempts, intervalSeconds }: PollTxOptions = {}
): Promise<Required<PlainMessage<GetTxResponse>>> {
public async broadcastTx(unsignedTx: UnsignedTx, fee: Fee): Promise<string> {
const { accountNumber, sequence } = await this.getAuthInfo(true);
const hash = await this.signAndBroadcastTx(
unsignedTx,
Expand All @@ -170,30 +166,50 @@ export abstract class ConnectedWallet {
// Greedily increment the sequence for the next tx. This may result in the wrong
// sequence, but if `estimateFee` was called prior to this, it will be corrected
this.sequence = sequence + 1n;
return hash;
}

/**
* Polls for the tx matching the given `txHash` every `intervalSeconds` until it is
* included in a block or when `maxAttempts` is reached (default: 2s, 64 attempts).
*
* @throws if the tx is not included in a block after the given `maxAttempts`.
*/
public async pollTx(
txHash: string,
{ maxAttempts, intervalSeconds }: PollTxOptions = {}
): Promise<Required<PlainMessage<GetTxResponse>>> {
return pollTx(this.rpc, {
hash,
hash: txHash,
maxAttempts,
intervalSeconds,
});
}

/**
* Executes `estimateFee` and `broadcastTx` sequentially, returning the result of
* the tx. Use this if there is no need independently execute the two methods.
* Executes `broadcastTx` and `pollTx` sequentially, returning the result of the
* tx. If `feeOrFeeMultiplier` is `undefined` or a number, an additional call to
* `estimateFee` will be made. Use this if there is no need to independently
* execute the three methods.
*/
public async broadcastTxWithFeeEstimation(
public async broadcastTxSync(
unsignedTx: UnsignedTx,
feeMultiplier = 1.4,
feeOrFeeMultiplier: Fee | number = 1.4,
pollOpts: PollTxOptions = {}
): Promise<Required<PlainMessage<GetTxResponse>>> {
const fee = await this.estimateFee(unsignedTx, feeMultiplier);
return this.broadcastTx(unsignedTx, fee, pollOpts);
const fee =
typeof feeOrFeeMultiplier === "number"
? await this.estimateFee(unsignedTx, feeOrFeeMultiplier)
: feeOrFeeMultiplier;
const txHash = await this.broadcastTx(unsignedTx, fee);
return this.pollTx(txHash, pollOpts);
}

/**
* Signs the UTF-8 encoded `data` string. Note that some mobile wallets do not
* support this method.
*
* @throws if the user denies the signing of the data.
* @throws if the wallet does not support signing arbitrary data.
*/
public abstract signArbitrary(data: string): Promise<SignArbitraryResponse>;
Expand Down
6 changes: 5 additions & 1 deletion src/wallet/wallets/mnemonic/MnemonicWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ export type ConnectMnemonicWalletOptions = Prettify<
* });
* console.log("Address:", wallet.address); // prints the bech32 address
*
* // Sign an arbitrary message
* const { signature } = await wallet.signArbitrary("Hello from CosmES!");
* console.log("Signature:", signature);
*
* // Sign and broadcast a tx
* const res = await wallet.broadcastTxWithFeeEstimation({ ... }); // TODO
* const res = await wallet.broadcastTxSync( ... ); // TODO
* console.log("Tx result:", res);
* ```
*/
Expand Down

0 comments on commit 1fcc8c9

Please sign in to comment.