Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically decode XDR structures in simulation responses #127

Merged
merged 9 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add test cases for new behavior
  • Loading branch information
Shaptic committed Aug 14, 2023
commit 4d635a23cb2d7df202bae3d38b5bd5b6ebf82d04
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ A breaking change should be clearly marked in this log.


### Breaking Changes
* `Server.prepareTransaction` now returns a `TransactionBuilder` instance rather than an immutable `Transaction`, in order to facilitate modifying your transaction after assembling it alongside the simulation response ([https://github.com/stellar/js-soroban-client/pull/127](#127)).
- The intent is to avoid cloning the transaction again (via `TransactionBuilder.cloneFrom`) if you need to modify parameters such as the storage access footprint.
- To migrate your code, just call `.build()` on the return value.
* The RPC response schemas for simulation have been upgraded to parse the base64-encoded XDR automatically. The full interface changes are in the pull request ([https://github.com/stellar/js-soroban-client/pull/127](#127)), but succinctly:
- `SimulateTransactionResponse` -> `RawSimulateTransactionResponse`
- `SimulateHostFunctionResult` -> `RawSimulateHostFunctionResult`
Expand Down
76 changes: 69 additions & 7 deletions test/unit/server/simulate_transaction_test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const xdr = SorobanClient.xdr;

describe("Server#simulateTransaction", function () {
let keypair = SorobanClient.Keypair.random();
let account = new SorobanClient.Account(
Expand All @@ -10,10 +12,12 @@ describe("Server#simulateTransaction", function () {
let address = contract.address().toScAddress();

const simulationResponse = {
transactionData: new SorobanClient.SorobanDataBuilder(),
id: 1,
events: [],
latestLedger: 3,
minResourceFee: "15",
result: {
transactionData: new SorobanClient.SorobanDataBuilder().build().toXDR('base64'),
results: [{
auth: [
new SorobanClient.xdr.SorobanAuthorizationEntry({
// Include a credentials w/ a nonce
Expand All @@ -38,17 +42,32 @@ describe("Server#simulateTransaction", function () {
),
subInvocations: [],
}),
})
}).toXDR('base64'),
],
xdr: SorobanClient.xdr.ScVal.scvU32(0),
},
latestLedger: 3,
xdr: SorobanClient.xdr.ScVal.scvU32(0).toXDR('base64'),
}],
cost: {
cpuInsns: "0",
memBytes: "0",
},
};

const parsedSimulationResponse = {
id: simulationResponse.id,
events: simulationResponse.events,
latestLedger: simulationResponse.latestLedger,
minResourceFee: simulationResponse.minResourceFee,
transactionData:
new SorobanClient.SorobanDataBuilder(simulationResponse.transactionData),
result: {
auth: simulationResponse.results[0].auth.map(
entry => SorobanClient.xdr.SorobanAuthorizationEntry.fromXDR(entry, 'base64')
),
retval: SorobanClient.xdr.ScVal.fromXDR(simulationResponse.results[0].xdr, 'base64'),
},
cost: simulationResponse.cost,
}

beforeEach(function () {
this.server = new SorobanClient.Server(serverUrl);
this.axiosMock = sinon.mock(AxiosClient);
Expand Down Expand Up @@ -103,13 +122,56 @@ describe("Server#simulateTransaction", function () {
this.server
.simulateTransaction(this.transaction)
.then(function (response) {
expect(response).to.be.deep.equal(simulationResponse);
expect(response).to.be.deep.equal(parsedSimulationResponse);
done();
})
.catch(function (err) {
done(err);
});
});

it("works when there are no results", function() {
const simResponseCopy = JSON.parse(JSON.stringify(simulationResponse));
simResponseCopy.results = undefined;

const parsedCopy = JSON.parse(JSON.stringify(parsedSimulationResponse));
parsedCopy.result = undefined;

const parsed = SorobanClient.parseRawSimulation(simResponseCopy)
expect(parsed).to.deep.equal(parsedCopy);
});

it("works with no auth", function(done) {
const simResponseCopy = JSON.parse(JSON.stringify(simulationResponse));
simResponseCopy.results[0].auth = undefined;

this.axiosMock
.expects("post")
.withArgs(serverUrl, {
jsonrpc: "2.0",
id: 1,
method: "simulateTransaction",
params: [this.blob],
})
.returns(
Promise.resolve({ data: { id: 1, result: simResponseCopy } })
);

this.server
.simulateTransaction(this.transaction)
.then(function (response) {
const parsedCopy = JSON.parse(JSON.stringify(parsedSimulationResponse));
parsedCopy.result.auth = [];

expect(response).to.be.deep.equal(parsedCopy,
`.result.auth should be [], got ${JSON.stringify(response)}`);
done();
})
.catch(function (err) {
done(err);
});
})

xit("adds metadata - tx was too small and was immediately deleted");
xit("adds metadata, order immediately fills");
xit("adds metadata, order is open");
Expand Down
25 changes: 11 additions & 14 deletions test/unit/transaction_test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
const xdr = SorobanClient.xdr; // shorthand

describe("assembleTransaction", () => {
describe("FeeBumpTransaction", () => {
// TODO: Add support for fee bump transactions
});
xit('works with keybump transactions');

const scAddress = new SorobanClient.Address(
"GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"
Expand Down Expand Up @@ -31,22 +29,20 @@ describe("assembleTransaction", () => {
),
subInvocations: [],
}),
});
}).toXDR();

const sorobanTransactionData = new SorobanClient.SorobanDataBuilder()
.setResources(0, 5, 0, 0)
.build();

const simulationResponse = {
transactionData: new SorobanClient.SorobanDataBuilder(
sorobanTransactionData
),
transactionData: sorobanTransactionData.toXDR('base64'),
events: [],
minResourceFee: "115",
results: [
{
auth: [fnAuth],
xdr: xdr.ScVal.scvU32(0),
xdr: xdr.ScVal.scvU32(0).toXDR('base64')
},
],
latestLedger: 3,
Expand All @@ -55,6 +51,7 @@ describe("assembleTransaction", () => {
memBytes: "0",
},
};

describe("Transaction", () => {
const networkPassphrase = SorobanClient.Networks.TESTNET;
const source = new SorobanClient.Account(
Expand Down Expand Up @@ -84,7 +81,7 @@ describe("assembleTransaction", () => {
txn,
networkPassphrase,
simulationResponse
);
).build();

// validate it auto updated the tx fees from sim response fees
// since it was greater than tx.fee
Expand All @@ -102,7 +99,7 @@ describe("assembleTransaction", () => {
txn,
networkPassphrase,
simulationResponse
);
).build();

expect(
result
Expand Down Expand Up @@ -147,7 +144,7 @@ describe("assembleTransaction", () => {
txn,
networkPassphrase,
simulateResp
);
).build();

expect(
result
Expand Down Expand Up @@ -182,7 +179,7 @@ describe("assembleTransaction", () => {
minResourceFee: "0",
results: [],
latestLedger: 3,
});
}).build();
expect.fail();
}).to.throw(/unsupported transaction/i);
});
Expand Down Expand Up @@ -210,7 +207,7 @@ describe("assembleTransaction", () => {
txn,
networkPassphrase,
simulationResponse
);
).build();
expect(tx.operations[0].type).to.equal(op.body().switch().name);
});
});
Expand All @@ -221,7 +218,7 @@ describe("assembleTransaction", () => {
txn,
networkPassphrase,
simulationResponse
);
).build();

expect(tx.operations[0].auth.length).to.equal(
3,
Expand Down