diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..3bad16e8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,10 @@ + + +# This is NOT the Turborepo you know + +Turborepo configuration, task behavior, and CLI commands can vary between installed versions and may differ from your training data. Resolve the `turbo` package from this file's directory or relevant workspace; in monorepos, it may not be visible from the repository root. For example, run `node -p "require.resolve('turbo/package.json')"` from a workspace that depends on `turbo`. + +Read `docs/README.md` inside that installed package first, then read the relevant pages from its `docs/` directory before changing Turborepo configuration or commands. Heed deprecation notices. These bundled docs match the installed package version and are available without network access. + +This block is written and re-added by `turbo` before repository-scoped commands when an AI agent is detected. In the Turborepo source repository, its template is defined in `crates/turborepo-cli/src/cli/agent_guidance.rs`. Removing the managed block while updates are enabled means a later qualifying invocation will add it again. Set `"agentGuidance": false` in the root `turbo.json` or `turbo.jsonc` to opt out; this does not remove an existing block. Keep the block committed with your work to avoid an uncommitted change on the next agent invocation. + diff --git a/packages/stellar-sdk-helpers/src/keeper-tx.ts b/packages/stellar-sdk-helpers/src/keeper-tx.ts index ad666b78..6d02ecf0 100644 --- a/packages/stellar-sdk-helpers/src/keeper-tx.ts +++ b/packages/stellar-sdk-helpers/src/keeper-tx.ts @@ -314,7 +314,7 @@ export interface KeeperTxConfig { // confirmed on-chain failure). Callers must persist `priorHash` across their // own retry attempts (see accrual-keeper.ts and migration-keeper.ts), and // persist it across invocations through `hooks` (see keeper-state.ts). -// `attempt` (1-indexed, matching withKeeperRetry's own callback, see +// `attempt` (0-indexed, matching withKeeperRetry's callback and // keeperFeeForAttempt above) sets the classic inclusion fee for a // freshly-built transaction, escalating on each retry so a // `txInsufficientFee` rejection has a real chance of clearing next time; diff --git a/packages/stellar-sdk-helpers/src/tx.test.ts b/packages/stellar-sdk-helpers/src/tx.test.ts index c7c44614..0632c37b 100644 --- a/packages/stellar-sdk-helpers/src/tx.test.ts +++ b/packages/stellar-sdk-helpers/src/tx.test.ts @@ -6,6 +6,7 @@ import { Asset, Contract, Operation, + SorobanDataBuilder, TransactionBuilder, nativeToScVal, xdr, @@ -246,6 +247,34 @@ describe("simErrorMessage snapshots", () => { describe("prepareSorobanTx contract errors", () => { afterEach(() => vi.restoreAllMocks()); + it("returns the total assembled fee including the inclusion fee", async () => { + const caller = "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5"; + vi.spyOn(rpc.Server.prototype, "getAccount").mockResolvedValue( + new Account(caller, "0") + ); + vi.spyOn(rpc.Server.prototype, "simulateTransaction").mockResolvedValue({ + id: "1", + latestLedger: 1, + minResourceFee: "500", + transactionData: new SorobanDataBuilder().build().toXDR("base64"), + events: [], + results: [{ auth: [], xdr: xdr.ScVal.scvVoid().toXDR("base64") }], + } as Awaited>); + + const result = await prepareSorobanTx( + { + network: "testnet", + rpcUrl: "https://soroban-testnet.stellar.org", + passphrase: "Test SDF Network ; September 2015", + }, + caller, + new Contract(CONTRACT_ADDRESSES.testnet.vault).call("deposit") + ); + + expect(result.fee).toBe("600"); + expect(result.xdr).toBeTruthy(); + }); + it.each([ ["HostError: Error(Contract, #18)", true], ["HostError: Error(Contract, #15)", true], diff --git a/packages/stellar-sdk-helpers/src/tx.ts b/packages/stellar-sdk-helpers/src/tx.ts index 9ccbfa05..de12e9dc 100644 --- a/packages/stellar-sdk-helpers/src/tx.ts +++ b/packages/stellar-sdk-helpers/src/tx.ts @@ -197,7 +197,8 @@ export async function simulateView( /** * Fetch the caller's account, simulate the operation to obtain the resource * footprint and fee, assemble the transaction, and return the unsigned XDR - * and minimum resource fee. Throws if simulation fails. + * and total fee (classic inclusion fee plus minimum resource fee). Throws + * if simulation fails. */ export async function prepareSorobanTx( network: StellarNetwork, @@ -234,7 +235,7 @@ export async function prepareSorobanTx( const prepared = rpc.assembleTransaction(tx, sim).build(); return { xdr: prepared.toEnvelope().toXDR("base64"), - fee: sim.minResourceFee, + fee: (BigInt(prepared.fee) + BigInt(sim.minResourceFee)).toString(), }; } diff --git a/packages/stellar-sdk-helpers/src/vaults.ts b/packages/stellar-sdk-helpers/src/vaults.ts index 6ae5224e..3689e121 100644 --- a/packages/stellar-sdk-helpers/src/vaults.ts +++ b/packages/stellar-sdk-helpers/src/vaults.ts @@ -156,7 +156,7 @@ async function fetchMeridianVault( "Meridian adapter RPC" ), ]); - const tvl = Math.round(Number(toBigInt(totalAssetsRaw) ?? 0n) / 1e7); + const tvl = Math.round(Number(toBigInt(totalAssetsRaw)) / 1e7); return { ...meta, asset: meta.asset ?? "USDC",