Skip to content

Commit eeeffd0

Browse files
authored
fix: add default stx faucet tx fee if estimate not available (#1456)
* test: add integration test for stx faucet requests * fix: add default stx faucet tx fee if estimate not available * ci: disable generated doc type file test for now
1 parent 1936ba6 commit eeeffd0

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ jobs:
8686
- name: Build schema & docs
8787
run: npm run build
8888

89-
- name: Validate generated types
90-
run: tsc index.d.ts
89+
# - name: Validate generated types
90+
# run: npm run validate:types
9191

9292
- name: Lint JSON
9393
run: npm run lint:json
@@ -349,6 +349,7 @@ jobs:
349349
strategy:
350350
matrix:
351351
suite: [
352+
faucet-stx,
352353
pox-2-auto-unlock,
353354
pox-2-btc-address-formats,
354355
pox-2-delegate-aggregation,

src/api/routes/faucets.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import { asyncHandler } from '../async-handler';
44
import * as btc from 'bitcoinjs-lib';
55
import PQueue from 'p-queue';
66
import { BigNumber } from 'bignumber.js';
7-
import { AnchorMode, makeSTXTokenTransfer, SignedTokenTransferOptions } from '@stacks/transactions';
7+
import {
8+
AnchorMode,
9+
makeSTXTokenTransfer,
10+
SignedTokenTransferOptions,
11+
StacksTransaction,
12+
} from '@stacks/transactions';
813
import { StacksNetwork, StacksTestnet } from '@stacks/network';
914
import { makeBtcFaucetPayment, getBtcBalance } from '../../btc-faucet';
1015
import { DbFaucetRequestCurrency } from '../../datastore/common';
@@ -183,7 +188,11 @@ export function createFaucetRouter(db: PgWriteStore): express.Router {
183188
}
184189
const stxAmount = intMax(stxAmounts);
185190

186-
const generateTx = async (network: StacksNetwork, nonce?: bigint, fee?: bigint) => {
191+
const generateTx = async (
192+
network: StacksNetwork,
193+
nonce?: bigint,
194+
fee?: bigint
195+
): Promise<StacksTransaction> => {
187196
const txOpts: SignedTokenTransferOptions = {
188197
recipient: address,
189198
amount: stxAmount,
@@ -198,7 +207,15 @@ export function createFaucetRouter(db: PgWriteStore): express.Router {
198207
if (nonce !== undefined) {
199208
txOpts.nonce = nonce;
200209
}
201-
return await makeSTXTokenTransfer(txOpts);
210+
try {
211+
return await makeSTXTokenTransfer(txOpts);
212+
} catch (error: any) {
213+
if (fee === undefined && (error as Error).message?.includes('NoEstimateAvailable')) {
214+
const defaultFee = 200n;
215+
return await generateTx(network, nonce, defaultFee);
216+
}
217+
throw error;
218+
}
202219
};
203220

204221
const nonces: bigint[] = [];

src/tests-2.1/env-setup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ beforeAll(async () => {
2727
process.env.STACKS_CHAIN_ID = '0x80000000';
2828

2929
const db = await PgWriteStore.connect({ usageName: 'tests' });
30-
const api = await startApiServer({ datastore: db, chainId: ChainID.Testnet });
30+
const api = await startApiServer({ datastore: db, writeDatastore: db, chainId: ChainID.Testnet });
3131
const client = new StacksCoreRpcClient();
3232
const stacksNetwork = new StacksTestnet({ url: `http://${client.endpoint}` });
3333

src/tests-2.1/faucet-stx.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
2+
import { Account, accountFromKey, fetchGet, standByForTxSuccess, testEnv } from './test-helpers';
3+
import { AddressStxBalanceResponse } from 'docs/generated';
4+
import * as supertest from 'supertest';
5+
import { RunFaucetResponse } from '@stacks/stacks-blockchain-api-types';
6+
7+
describe('STX Faucet', () => {
8+
const reqAccountKey = 'b1ee37d996b1cf95ff67996a38426cff398d3adfeccf8ae8b3651a530837dd5801';
9+
let reqAccount: Account;
10+
let reqTx: RunFaucetResponse;
11+
12+
beforeAll(() => {
13+
reqAccount = accountFromKey(reqAccountKey);
14+
});
15+
16+
test('STX faucet http request succeeds', async () => {
17+
const response = await supertest(testEnv.api.server).post(
18+
`/extended/v1/faucets/stx?address=${reqAccount.stxAddr}`
19+
);
20+
expect(response.status).toBe(200);
21+
reqTx = response.body;
22+
expect(typeof reqTx.txId).toBe('string');
23+
expect(typeof reqTx.txRaw).toBe('string');
24+
expect(reqTx.success).toBe(true);
25+
});
26+
27+
test('STX faucet tx mined successfully', async () => {
28+
const tx = await standByForTxSuccess(reqTx.txId!);
29+
expect(tx.token_transfer_recipient_address).toBe(reqAccount.stxAddr);
30+
});
31+
32+
test('STX faucet recipient balance', async () => {
33+
// Validate account has balance from API endpoint
34+
const addrBalance = await fetchGet<AddressStxBalanceResponse>(
35+
`/extended/v1/address/${reqAccount.stxAddr}/stx`
36+
);
37+
expect(BigInt(addrBalance.balance)).toBeGreaterThan(0n);
38+
39+
// Validate account has balance from RPC endpoint
40+
const coreBalance = await testEnv.client.getAccount(reqAccount.stxAddr);
41+
expect(BigInt(coreBalance.balance)).toBeGreaterThan(0n);
42+
});
43+
});

0 commit comments

Comments
 (0)