From 9345c29f3e8538f829059fa35141111d3feed237 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Thu, 17 Oct 2024 17:07:04 +0200 Subject: [PATCH 1/2] feat: detect chain-id by default for testnet networks in tx builder functions --- packages/cli/tests/cli.test.ts | 24 +++++++++--- packages/transactions/src/builders.ts | 40 +++++++++++++++++++ packages/transactions/tests/builder.test.ts | 43 ++++++++++++++++----- 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/packages/cli/tests/cli.test.ts b/packages/cli/tests/cli.test.ts index 2670adc0e..32f601f43 100644 --- a/packages/cli/tests/cli.test.ts +++ b/packages/cli/tests/cli.test.ts @@ -24,7 +24,7 @@ import { WalletKeyInfoResult, } from './derivation-path/keychain'; import * as fixtures from './fixtures/cli.fixture'; -import { bytesToHex } from '@stacks/common'; +import { bytesToHex, ChainID } from '@stacks/common'; const TEST_ABI: ClarityAbi = JSON.parse( readFileSync(path.join(__dirname, './abi/test-abi.json')).toString() @@ -111,7 +111,9 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)); + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + fetchMock.once('success'); const txid = '0x6c764e276b500babdac6cec159667f4b68938d31eee82419473a418222af7d5d'; const result = await contractFunctionCall(testnetNetwork, args); @@ -132,7 +134,9 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)); + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + fetchMock.once('success'); const txid = '0x97f41dfa44a5833acd9ca30ffe31d7137623c0e31a5c6467daeed8e61a03f51c'; const result = await contractFunctionCall(testnetNetwork, args); @@ -153,7 +157,9 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)); + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + fetchMock.once('success'); const txid = '0x5fc468f21345c5ecaf1c007fce9630d9a79ec1945ed8652cc3c42fb542e35fe2'; const result = await contractFunctionCall(testnetNetwork, args); @@ -178,7 +184,9 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)); + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + fetchMock.once('success'); const txid = '0x94b1cfab79555b8c6725f19e4fcd6268934d905578a3e8ef7a1e542b931d3676'; const result = await contractFunctionCall(testnetNetwork, args); @@ -201,7 +209,9 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)); + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + fetchMock.once('success'); const txid = '0x6b6cd5bfb44c46a68090f0c5f659e9cc02518eafab67b0b740e1e77a55bbf284'; const result = await contractFunctionCall(testnetNetwork, args); @@ -286,6 +296,7 @@ describe('BNS', () => { fetchMock.mockOnce(mockedResponse); fetchMock.mockRejectOnce(); fetchMock.mockOnce(JSON.stringify({ nonce: 1000 })); + fetchMock.mockOnce(JSON.stringify({ network_id: ChainID.Testnet })); fetchMock.mockOnce(JSON.stringify('success')); const txResult = await register(testnetNetwork, args); @@ -306,6 +317,7 @@ describe('BNS', () => { fetchMock.mockOnce(mockedResponse); fetchMock.mockRejectOnce(); fetchMock.mockOnce(JSON.stringify({ nonce: 1000 })); + fetchMock.mockOnce(JSON.stringify({ network_id: ChainID.Testnet })); fetchMock.mockOnce(JSON.stringify('success')); const txResult = await preorder(testnetNetwork, args); diff --git a/packages/transactions/src/builders.ts b/packages/transactions/src/builders.ts index e827bc1f6..3de0eb189 100644 --- a/packages/transactions/src/builders.ts +++ b/packages/transactions/src/builders.ts @@ -116,6 +116,30 @@ export async function getNonce( return BigInt(result.nonce); } +/** + * Fetch the network chain ID from a given network. Typically used for looking up the chain ID for a non-default testnet network. + * @param useDefaultOnError - If the network fetch fails then return the default chain ID already specifed in the `network` arg. + */ +export async function getNetworkChainID(network: StacksNetwork, useDefaultOnError = true) { + const url = network.getInfoUrl(); + try { + const response = await network.fetchFn(url); + if (!response.ok) { + const msg = await response.text().catch(() => ''); + throw new Error(`Bad response status ${response.status} ${response.statusText}: "${msg}"`); + } + const responseJson: { network_id: number } = await response.json(); + return responseJson.network_id; + } catch (error) { + if (!useDefaultOnError) { + throw error; + } + // log error and return default nework chain ID + console.warn(`Error fetching network chain ID from ${url}`, error); + return network.chainId; + } +} + /** * @deprecated Use the new {@link estimateTransaction} function instead. * @@ -751,6 +775,11 @@ export async function makeUnsignedSTXTokenTransfer( transaction.setNonce(txNonce); } + // Lookup chain ID for testnet networks + if (network.version !== TransactionVersion.Mainnet) { + transaction.chainId = await getNetworkChainID(network); + } + return transaction; } @@ -1024,6 +1053,12 @@ export async function makeUnsignedContractDeploy( transaction.setNonce(txNonce); } + // Lookup chain ID for testnet networks + if (network.version !== TransactionVersion.Mainnet) { + transaction.chainId = await getNetworkChainID(network); + } + + return transaction; } @@ -1237,6 +1272,11 @@ export async function makeUnsignedContractCall( transaction.setNonce(txNonce); } + // Lookup chain ID for testnet networks + if (network.version !== TransactionVersion.Mainnet) { + transaction.chainId = await getNetworkChainID(network); + } + return transaction; } diff --git a/packages/transactions/tests/builder.test.ts b/packages/transactions/tests/builder.test.ts index cbf5cea2a..1c9b68b97 100644 --- a/packages/transactions/tests/builder.test.ts +++ b/packages/transactions/tests/builder.test.ts @@ -1,4 +1,5 @@ import { + ChainID, PRIVATE_KEY_COMPRESSED_LENGTH, bytesToHex, bytesToUtf8, @@ -1242,6 +1243,9 @@ test('Estimate transaction fee fallback', async () => { // http://localhost:3999/v2/fees/transfer fetchMock.once('1'); + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const tx = await makeContractCall({ senderKey: privateKey, contractAddress: 'ST000000000000000000002AMW42H', @@ -1291,7 +1295,7 @@ test('Estimate transaction fee fallback', async () => { const doubleRate = await estimateTransactionFeeWithFallback(tx, testnet); expect(doubleRate).toBe(402n); - expect(fetchMock.mock.calls.length).toEqual(8); + expect(fetchMock.mock.calls.length).toEqual(9); }); test('Single-sig transaction byte length must include signature', async () => { @@ -1427,6 +1431,9 @@ test('Make STX token transfer with fetch account nonce', async () => { fetchMock.mockRejectOnce(); fetchMock.mockOnce(`{"balance":"0", "nonce":${nonce}}`); + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const transaction = await makeSTXTokenTransfer({ recipient, amount, @@ -1437,9 +1444,10 @@ test('Make STX token transfer with fetch account nonce', async () => { anchorMode: AnchorMode.Any, }); - expect(fetchMock.mock.calls.length).toEqual(4); + expect(fetchMock.mock.calls.length).toEqual(5); expect(fetchMock.mock.calls[1][0]).toEqual(apiUrl); expect(fetchMock.mock.calls[3][0]).toEqual(apiUrl); + expect(fetchMock.mock.calls[4][0]).toEqual(network.getInfoUrl()); expect(fetchNonce.toString()).toEqual(nonce.toString()); expect(transaction.auth.spendingCondition?.nonce?.toString()).toEqual(nonce.toString()); }); @@ -1670,6 +1678,9 @@ test('Make sponsored STX token transfer with set tx fee', async () => { const sponsorNonce = 0; const sponsorFee = 500; + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const transaction = await makeSTXTokenTransfer({ recipient, amount, @@ -1695,7 +1706,7 @@ test('Make sponsored STX token transfer with set tx fee', async () => { const bytesReader = new BytesReader(sponsorSignedTxSerialized); const deserializedSponsorTx = deserializeTransaction(bytesReader); - expect(fetchMock.mock.calls.length).toEqual(0); + expect(fetchMock.mock.calls.length).toEqual(1); expect(deserializedSponsorTx.auth.spendingCondition!.nonce!.toString()).toBe(nonce.toString()); expect(deserializedSponsorTx.auth.spendingCondition!.fee!.toString()).toBe(fee.toString()); @@ -1725,6 +1736,9 @@ test('Make sponsored contract deploy with sponsor fee estimate', async () => { const authType = AuthType.Sponsored; const addressHashMode = AddressHashMode.SerializeP2PKH; + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const transaction = await makeContractDeploy({ contractName, codeBody, @@ -1745,7 +1759,7 @@ test('Make sponsored contract deploy with sponsor fee estimate', async () => { const sponsorSignedTx = await sponsorTransaction(sponsorOptions); - expect(fetchMock.mock.calls.length).toEqual(0); + expect(fetchMock.mock.calls.length).toEqual(1); const sponsorSignedTxSerialized = sponsorSignedTx.serialize(); @@ -1784,6 +1798,9 @@ test('Make sponsored contract call with sponsor nonce fetch', async () => { const authType = AuthType.Sponsored; const addressHashMode = AddressHashMode.SerializeP2PKH; + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const transaction = await makeContractCall({ contractAddress, contractName, @@ -1808,8 +1825,8 @@ test('Make sponsored contract call with sponsor nonce fetch', async () => { const sponsorSignedTx = await sponsorTransaction(sponsorOptions); - expect(fetchMock.mock.calls.length).toEqual(2); - expect(fetchMock.mock.calls[1][0]).toEqual(network.getAccountApiUrl(sponsorAddress)); + expect(fetchMock.mock.calls.length).toEqual(3); + expect(fetchMock.mock.calls[2][0]).toEqual(network.getAccountApiUrl(sponsorAddress)); const sponsorSignedTxSerialized = sponsorSignedTx.serialize(); @@ -1883,6 +1900,9 @@ test('Transaction broadcast success with string network name', async () => { }); test('Transaction broadcast success with network detection', async () => { + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + const transaction = await makeSTXTokenTransfer({ recipient: standardPrincipalCV('SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'), amount: 12345, @@ -1898,9 +1918,9 @@ test('Transaction broadcast success with network detection', async () => { const response: TxBroadcastResult = await broadcastTransaction(transaction); - expect(fetchMock.mock.calls.length).toEqual(1); - expect(fetchMock.mock.calls[0][0]).toEqual(new StacksTestnet().getBroadcastApiUrl()); - expect(fetchMock.mock.calls[0][1]?.body).toEqual(transaction.serialize()); + expect(fetchMock.mock.calls.length).toEqual(2); + expect(fetchMock.mock.calls[1][0]).toEqual(new StacksTestnet().getBroadcastApiUrl()); + expect(fetchMock.mock.calls[1][1]?.body).toEqual(transaction.serialize()); expect(response as TxBroadcastResultOk).toEqual({ txid: 'success' }); }); @@ -2018,6 +2038,9 @@ test('Make contract-call with network ABI validation', async () => { const abi = fs.readFileSync('./tests/abi/kv-store-abi.json').toString(); fetchMock.mockOnce(abi); + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); + await makeContractCall({ contractAddress, contractName, @@ -2032,7 +2055,7 @@ test('Make contract-call with network ABI validation', async () => { anchorMode: AnchorMode.Any, }); - expect(fetchMock.mock.calls.length).toEqual(1); + expect(fetchMock.mock.calls.length).toEqual(2); expect(fetchMock.mock.calls[0][0]).toEqual(network.getAbiApiUrl(contractAddress, contractName)); }); From 0c509c33441c221b2928d753bf2e9efa6d1bca51 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Thu, 17 Oct 2024 17:36:40 +0200 Subject: [PATCH 2/2] chore: also skip chainID lookup for primary testnet urls --- packages/cli/tests/cli.test.ts | 24 ++----- packages/transactions/src/builders.ts | 21 ++++-- packages/transactions/tests/builder.test.ts | 78 +++++++++++++-------- 3 files changed, 70 insertions(+), 53 deletions(-) diff --git a/packages/cli/tests/cli.test.ts b/packages/cli/tests/cli.test.ts index 32f601f43..2670adc0e 100644 --- a/packages/cli/tests/cli.test.ts +++ b/packages/cli/tests/cli.test.ts @@ -24,7 +24,7 @@ import { WalletKeyInfoResult, } from './derivation-path/keychain'; import * as fixtures from './fixtures/cli.fixture'; -import { bytesToHex, ChainID } from '@stacks/common'; +import { bytesToHex } from '@stacks/common'; const TEST_ABI: ClarityAbi = JSON.parse( readFileSync(path.join(__dirname, './abi/test-abi.json')).toString() @@ -111,9 +111,7 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)); - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - fetchMock.once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); const txid = '0x6c764e276b500babdac6cec159667f4b68938d31eee82419473a418222af7d5d'; const result = await contractFunctionCall(testnetNetwork, args); @@ -134,9 +132,7 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)); - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - fetchMock.once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); const txid = '0x97f41dfa44a5833acd9ca30ffe31d7137623c0e31a5c6467daeed8e61a03f51c'; const result = await contractFunctionCall(testnetNetwork, args); @@ -157,9 +153,7 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)); - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - fetchMock.once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); const txid = '0x5fc468f21345c5ecaf1c007fce9630d9a79ec1945ed8652cc3c42fb542e35fe2'; const result = await contractFunctionCall(testnetNetwork, args); @@ -184,9 +178,7 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)); - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - fetchMock.once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); const txid = '0x94b1cfab79555b8c6725f19e4fcd6268934d905578a3e8ef7a1e542b931d3676'; const result = await contractFunctionCall(testnetNetwork, args); @@ -209,9 +201,7 @@ describe('Contract function call', () => { // @ts-ignore inquirer.prompt = jest.fn().mockResolvedValue(contractInputArg); - fetchMock.once(JSON.stringify(TEST_ABI)); - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - fetchMock.once('success'); + fetchMock.once(JSON.stringify(TEST_ABI)).once('success'); const txid = '0x6b6cd5bfb44c46a68090f0c5f659e9cc02518eafab67b0b740e1e77a55bbf284'; const result = await contractFunctionCall(testnetNetwork, args); @@ -296,7 +286,6 @@ describe('BNS', () => { fetchMock.mockOnce(mockedResponse); fetchMock.mockRejectOnce(); fetchMock.mockOnce(JSON.stringify({ nonce: 1000 })); - fetchMock.mockOnce(JSON.stringify({ network_id: ChainID.Testnet })); fetchMock.mockOnce(JSON.stringify('success')); const txResult = await register(testnetNetwork, args); @@ -317,7 +306,6 @@ describe('BNS', () => { fetchMock.mockOnce(mockedResponse); fetchMock.mockRejectOnce(); fetchMock.mockOnce(JSON.stringify({ nonce: 1000 })); - fetchMock.mockOnce(JSON.stringify({ network_id: ChainID.Testnet })); fetchMock.mockOnce(JSON.stringify('success')); const txResult = await preorder(testnetNetwork, args); diff --git a/packages/transactions/src/builders.ts b/packages/transactions/src/builders.ts index 3de0eb189..c235f90cc 100644 --- a/packages/transactions/src/builders.ts +++ b/packages/transactions/src/builders.ts @@ -6,6 +6,7 @@ import { StacksTestnet, FetchFn, createFetchFn, + HIRO_TESTNET_DEFAULT, } from '@stacks/network'; import { c32address } from 'c32check'; import { @@ -140,6 +141,13 @@ export async function getNetworkChainID(network: StacksNetwork, useDefaultOnErro } } +function isNetworkCustomTestnet(network: StacksNetwork) { + return ( + network.version !== TransactionVersion.Mainnet && + new URL(network.coreApiUrl).host !== new URL(HIRO_TESTNET_DEFAULT).host + ); +} + /** * @deprecated Use the new {@link estimateTransaction} function instead. * @@ -775,8 +783,8 @@ export async function makeUnsignedSTXTokenTransfer( transaction.setNonce(txNonce); } - // Lookup chain ID for testnet networks - if (network.version !== TransactionVersion.Mainnet) { + // Lookup chain ID for (non-primary) testnet networks + if (isNetworkCustomTestnet(network)) { transaction.chainId = await getNetworkChainID(network); } @@ -1053,12 +1061,11 @@ export async function makeUnsignedContractDeploy( transaction.setNonce(txNonce); } - // Lookup chain ID for testnet networks - if (network.version !== TransactionVersion.Mainnet) { + // Lookup chain ID for (non-primary) testnet networks + if (isNetworkCustomTestnet(network)) { transaction.chainId = await getNetworkChainID(network); } - return transaction; } @@ -1272,8 +1279,8 @@ export async function makeUnsignedContractCall( transaction.setNonce(txNonce); } - // Lookup chain ID for testnet networks - if (network.version !== TransactionVersion.Mainnet) { + // Lookup chain ID for (non-primary) testnet networks + if (isNetworkCustomTestnet(network)) { transaction.chainId = await getNetworkChainID(network); } diff --git a/packages/transactions/tests/builder.test.ts b/packages/transactions/tests/builder.test.ts index 1c9b68b97..2da995c13 100644 --- a/packages/transactions/tests/builder.test.ts +++ b/packages/transactions/tests/builder.test.ts @@ -333,6 +333,47 @@ test('Make STX token transfer with testnet string name', async () => { expect(serialized).toBe(tx); }); +test('Make STX token transfer with custom testnet (lookup network chainID)', async () => { + const nonce = 123; + const recipient = standardPrincipalCV('SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'); + const amount = 12345; + const fee = 0; + const senderKey = 'cb3df38053d132895220b9ce471f6b676db5b9bf0b4adefb55f2118ece2478df01'; + const senderAddress = 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6'; + const memo = 'test memo'; + const network = new StacksTestnet({ url: 'https://my-custom-testnet.example' }); + const apiUrl = network.getAccountApiUrl(senderAddress); + + fetchMock.mockRejectOnce(); + fetchMock.mockOnce(`{"balance":"0", "nonce":${nonce}}`); + + const fetchNonce = await getNonce(senderAddress, network); + + fetchMock.mockRejectOnce(); + fetchMock.mockOnce(`{"balance":"0", "nonce":${nonce}}`); + + // http://localhost:3999/v2/info + fetchMock.once(JSON.stringify({ network_id: 0x1234 })); + + const transaction = await makeSTXTokenTransfer({ + recipient, + amount, + senderKey, + fee, + memo, + network, + anchorMode: AnchorMode.Any, + }); + + expect(fetchMock.mock.calls.length).toEqual(5); + expect(fetchMock.mock.calls[1][0]).toEqual(apiUrl); + expect(fetchMock.mock.calls[3][0]).toEqual(apiUrl); + expect(fetchMock.mock.calls[4][0]).toEqual(network.getInfoUrl()); + expect(fetchNonce.toString()).toEqual(nonce.toString()); + expect(transaction.auth.spendingCondition?.nonce?.toString()).toEqual(nonce.toString()); + expect(transaction.chainId).toEqual(0x1234); +}); + test('Throws making STX token transder with invalid network name', async () => { const txOptions = { recipient: standardPrincipalCV('SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'), @@ -1431,9 +1472,6 @@ test('Make STX token transfer with fetch account nonce', async () => { fetchMock.mockRejectOnce(); fetchMock.mockOnce(`{"balance":"0", "nonce":${nonce}}`); - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - const transaction = await makeSTXTokenTransfer({ recipient, amount, @@ -1444,10 +1482,9 @@ test('Make STX token transfer with fetch account nonce', async () => { anchorMode: AnchorMode.Any, }); - expect(fetchMock.mock.calls.length).toEqual(5); + expect(fetchMock.mock.calls.length).toEqual(4); expect(fetchMock.mock.calls[1][0]).toEqual(apiUrl); expect(fetchMock.mock.calls[3][0]).toEqual(apiUrl); - expect(fetchMock.mock.calls[4][0]).toEqual(network.getInfoUrl()); expect(fetchNonce.toString()).toEqual(nonce.toString()); expect(transaction.auth.spendingCondition?.nonce?.toString()).toEqual(nonce.toString()); }); @@ -1678,9 +1715,6 @@ test('Make sponsored STX token transfer with set tx fee', async () => { const sponsorNonce = 0; const sponsorFee = 500; - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - const transaction = await makeSTXTokenTransfer({ recipient, amount, @@ -1706,7 +1740,7 @@ test('Make sponsored STX token transfer with set tx fee', async () => { const bytesReader = new BytesReader(sponsorSignedTxSerialized); const deserializedSponsorTx = deserializeTransaction(bytesReader); - expect(fetchMock.mock.calls.length).toEqual(1); + expect(fetchMock.mock.calls.length).toEqual(0); expect(deserializedSponsorTx.auth.spendingCondition!.nonce!.toString()).toBe(nonce.toString()); expect(deserializedSponsorTx.auth.spendingCondition!.fee!.toString()).toBe(fee.toString()); @@ -1736,9 +1770,6 @@ test('Make sponsored contract deploy with sponsor fee estimate', async () => { const authType = AuthType.Sponsored; const addressHashMode = AddressHashMode.SerializeP2PKH; - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - const transaction = await makeContractDeploy({ contractName, codeBody, @@ -1759,7 +1790,7 @@ test('Make sponsored contract deploy with sponsor fee estimate', async () => { const sponsorSignedTx = await sponsorTransaction(sponsorOptions); - expect(fetchMock.mock.calls.length).toEqual(1); + expect(fetchMock.mock.calls.length).toEqual(0); const sponsorSignedTxSerialized = sponsorSignedTx.serialize(); @@ -1798,9 +1829,6 @@ test('Make sponsored contract call with sponsor nonce fetch', async () => { const authType = AuthType.Sponsored; const addressHashMode = AddressHashMode.SerializeP2PKH; - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - const transaction = await makeContractCall({ contractAddress, contractName, @@ -1825,8 +1853,8 @@ test('Make sponsored contract call with sponsor nonce fetch', async () => { const sponsorSignedTx = await sponsorTransaction(sponsorOptions); - expect(fetchMock.mock.calls.length).toEqual(3); - expect(fetchMock.mock.calls[2][0]).toEqual(network.getAccountApiUrl(sponsorAddress)); + expect(fetchMock.mock.calls.length).toEqual(2); + expect(fetchMock.mock.calls[1][0]).toEqual(network.getAccountApiUrl(sponsorAddress)); const sponsorSignedTxSerialized = sponsorSignedTx.serialize(); @@ -1900,9 +1928,6 @@ test('Transaction broadcast success with string network name', async () => { }); test('Transaction broadcast success with network detection', async () => { - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - const transaction = await makeSTXTokenTransfer({ recipient: standardPrincipalCV('SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'), amount: 12345, @@ -1918,9 +1943,9 @@ test('Transaction broadcast success with network detection', async () => { const response: TxBroadcastResult = await broadcastTransaction(transaction); - expect(fetchMock.mock.calls.length).toEqual(2); - expect(fetchMock.mock.calls[1][0]).toEqual(new StacksTestnet().getBroadcastApiUrl()); - expect(fetchMock.mock.calls[1][1]?.body).toEqual(transaction.serialize()); + expect(fetchMock.mock.calls.length).toEqual(1); + expect(fetchMock.mock.calls[0][0]).toEqual(new StacksTestnet().getBroadcastApiUrl()); + expect(fetchMock.mock.calls[0][1]?.body).toEqual(transaction.serialize()); expect(response as TxBroadcastResultOk).toEqual({ txid: 'success' }); }); @@ -2038,9 +2063,6 @@ test('Make contract-call with network ABI validation', async () => { const abi = fs.readFileSync('./tests/abi/kv-store-abi.json').toString(); fetchMock.mockOnce(abi); - // http://localhost:3999/v2/info - fetchMock.once(JSON.stringify({ network_id: ChainID.Testnet })); - await makeContractCall({ contractAddress, contractName, @@ -2055,7 +2077,7 @@ test('Make contract-call with network ABI validation', async () => { anchorMode: AnchorMode.Any, }); - expect(fetchMock.mock.calls.length).toEqual(2); + expect(fetchMock.mock.calls.length).toEqual(1); expect(fetchMock.mock.calls[0][0]).toEqual(network.getAbiApiUrl(contractAddress, contractName)); });