From 446ac24315de5508abd6b7acfee0f02c6c5980e3 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:53:27 -0400 Subject: [PATCH] fix: update simulationData after re-simulation The new test added here shows that you can edit a transaction with `tx.raw = cloneFrom(tx.build)` and that the `tx.simulationData` will be updated correctly. --- src/contract/assembled_transaction.ts | 4 ++ test/e2e/src/test-swap.js | 66 +++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/contract/assembled_transaction.ts b/src/contract/assembled_transaction.ts index 1f46824b9..c2d5e3ec1 100644 --- a/src/contract/assembled_transaction.ts +++ b/src/contract/assembled_transaction.ts @@ -422,6 +422,10 @@ export class AssembledTransaction { this.built = this.raw.build(); this.simulation = await this.server.simulateTransaction(this.built); + // need to force re-calculation of simulationData for new simulation + delete this.simulationResult; + delete this.simulationTransactionData; + if (Api.isSimulationSuccess(this.simulation)) { this.built = assembleTransaction( this.built, diff --git a/test/e2e/src/test-swap.js b/test/e2e/src/test-swap.js index 129c181be..a1128e827 100644 --- a/test/e2e/src/test-swap.js +++ b/test/e2e/src/test-swap.js @@ -1,7 +1,17 @@ -const { expect } = require('chai'); -const { describe, it, before } = require('mocha'); -const { contract, rpc } = require("../../.."); -const { clientFor, generateFundedKeypair } = require("./util"); +const { expect } = require("chai"); +const { describe, it, before } = require("mocha"); +const { + contract, + rpc, + SorobanDataBuilder, + xdr, + TransactionBuilder, +} = require("../../.."); +const { + clientFor, + generateFundedKeypair, + networkPassphrase, +} = require("./util"); const amountAToSwap = 2n; const amountBToSwap = 1n; @@ -74,7 +84,7 @@ describe("Swap Contract Tests", function () { // Further assertions on the error object expect(error).to.be.instanceOf(contract.AssembledTransaction.Errors.NeedsMoreSignatures, `error is not of type 'NeedsMoreSignaturesError'; instead it is of type '${error?.constructor.name}'`); - + if (error) { // Using regex to check the error message expect(error.message).to.match(/needsNonInvokerSigningBy/); @@ -82,6 +92,52 @@ describe("Swap Contract Tests", function () { }); }); + it("modified & re-simulated transactions show updated data", async function () { + const tx = await this.context.swapContractAsRoot.swap({ + a: this.context.alice.publicKey(), + b: this.context.bob.publicKey(), + token_a: this.context.tokenAId, + token_b: this.context.tokenBId, + amount_a: amountAToSwap, + min_a_for_b: amountAToSwap, + amount_b: amountBToSwap, + min_b_for_a: amountBToSwap, + }); + await tx.signAuthEntries({ + publicKey: this.context.alice.publicKey(), + ...contract.basicNodeSigner(this.context.alice, networkPassphrase), + }); + await tx.signAuthEntries({ + publicKey: this.context.bob.publicKey(), + ...contract.basicNodeSigner(this.context.bob, networkPassphrase), + }); + + const originalResourceFee = Number( + tx.simulationData.transactionData.resourceFee() + ); + const bumpedResourceFee = originalResourceFee + 10000; + + tx.raw = TransactionBuilder.cloneFrom(tx.built, { + fee: tx.built.fee, + sorobanData: new SorobanDataBuilder( + tx.simulationData.transactionData.toXDR() + ) + .setResourceFee( + xdr.Int64.fromString(bumpedResourceFee.toString()).toBigInt() + ) + .build(), + }); + + await tx.simulate(); + + const newSimulatedResourceFee = Number( + tx.simulationData.transactionData.resourceFee() + ); + + expect(originalResourceFee).to.not.equal(newSimulatedResourceFee); + expect(newSimulatedResourceFee).to.be.greaterThan(bumpedResourceFee); + }); + it("alice swaps bob 10 A for 1 B", async function() { const tx = await this.context.swapContractAsRoot.swap({ a: this.context.alice.publicKey(),