From ecaaa92497cc9f94f25e027ab2399930a9fc051e Mon Sep 17 00:00:00 2001 From: pritsheth Date: Fri, 10 May 2024 12:02:51 -0700 Subject: [PATCH 01/10] Add stateDiff in SimulateTransaction API response --- src/soroban/api.ts | 20 ++++++++++++-- .../soroban/simulate_transaction_test.js | 27 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/soroban/api.ts b/src/soroban/api.ts index 3c8d7806f..d64fc951a 100644 --- a/src/soroban/api.ts +++ b/src/soroban/api.ts @@ -175,8 +175,18 @@ export namespace Api { value: string; } - export interface RequestAirdropResponse { - transaction_id: string; + interface RawLedgerEntryDiff { + type: number; + key: string; + before?: string; + after?: string; + } + + interface LedgerEntryDiff{ + type: number; + key: string; + before?: xdr.LedgerEntry; + after?: xdr.LedgerEntry; } export type SendTransactionStatus = @@ -264,6 +274,9 @@ export namespace Api { /** present only for invocation simulation */ result?: SimulateHostFunctionResult; + + // State Difference information + stateDiff?: LedgerEntryDiff[]; } /** Includes details about why the simulation failed */ @@ -347,5 +360,8 @@ export namespace Api { minResourceFee: string; transactionData: string; }; + + // State Difference information + stateDiff?: RawLedgerEntryDiff[]; } } diff --git a/test/unit/server/soroban/simulate_transaction_test.js b/test/unit/server/soroban/simulate_transaction_test.js index f1c2bacbc..87f6f8bbe 100644 --- a/test/unit/server/soroban/simulate_transaction_test.js +++ b/test/unit/server/soroban/simulate_transaction_test.js @@ -32,6 +32,18 @@ describe("Server#simulateTransaction", async function (done) { retval: xdr.ScVal.fromXDR(simulationResponse.results[0].xdr, "base64"), }, cost: simulationResponse.cost, + stateDiff: [{ + type:1, + key: 'example-key', + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }), + }], _parsed: true, }; @@ -175,6 +187,7 @@ describe("Server#simulateTransaction", async function (done) { delete expected.cost; delete expected.transactionData; delete expected.minResourceFee; + delete expected.stateDiff expected.error = "This is an error"; expected.events = []; @@ -200,6 +213,7 @@ function cloneSimulation(sim) { retval: xdr.ScVal.fromXDR(sim.result.retval.toXDR()), }, cost: sim.cost, + stateDiff: sim.stateDiff, _parsed: sim._parsed, }; } @@ -262,6 +276,19 @@ function baseSimulationResponse(results) { cpuInsns: "1", memBytes: "2", }, + stateDiff:[{ + type:1, + key: 'example-key', + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }).toXDR('base64'), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }).toXDR('base64'), + }], + }; } From 33985fcb3833ca2814ddb31ebe72d67ae8fc0271 Mon Sep 17 00:00:00 2001 From: pritsheth Date: Fri, 10 May 2024 13:24:26 -0700 Subject: [PATCH 02/10] Add parsing of stateDiff --- src/soroban/api.ts | 2 ++ src/soroban/parsers.ts | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/soroban/api.ts b/src/soroban/api.ts index d64fc951a..af73abb61 100644 --- a/src/soroban/api.ts +++ b/src/soroban/api.ts @@ -178,7 +178,9 @@ export namespace Api { interface RawLedgerEntryDiff { type: number; key: string; + // these are xdr.LedgerEntry in base64 before?: string; + // these are xdr.LedgerEntry in base64 after?: string; } diff --git a/src/soroban/parsers.ts b/src/soroban/parsers.ts index 8ff1d1c6d..26a9b666f 100644 --- a/src/soroban/parsers.ts +++ b/src/soroban/parsers.ts @@ -139,7 +139,18 @@ function parseSuccessful( : xdr.ScVal.scvVoid() }; })[0] - }) + }), + + stateDiff: sim.stateDiff?.length ?? 0 > 0 + ? sim.stateDiff!.map((entryDiff) => { + return { + type: entryDiff.type, + key: entryDiff.key, + before: xdr.LedgerEntry.fromXDR(entryDiff.before, 'base64'), + after: xdr.LedgerEntry.fromXDR(entryDiff.after, 'base64'), + }; + }) + : null, }; if (!sim.restorePreamble || sim.restorePreamble.transactionData === '') { From 84eda50d2b9bbadd4c17e1602dc089c1dde9a803 Mon Sep 17 00:00:00 2001 From: pritsheth Date: Fri, 10 May 2024 13:37:44 -0700 Subject: [PATCH 03/10] Fix undefined type issues --- src/soroban/parsers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/soroban/parsers.ts b/src/soroban/parsers.ts index 26a9b666f..b734632b5 100644 --- a/src/soroban/parsers.ts +++ b/src/soroban/parsers.ts @@ -146,11 +146,11 @@ function parseSuccessful( return { type: entryDiff.type, key: entryDiff.key, - before: xdr.LedgerEntry.fromXDR(entryDiff.before, 'base64'), - after: xdr.LedgerEntry.fromXDR(entryDiff.after, 'base64'), + before: !!entryDiff.before ? xdr.LedgerEntry.fromXDR(entryDiff.before, 'base64') : undefined, + after: !!entryDiff.after ? xdr.LedgerEntry.fromXDR(entryDiff.after, 'base64') : undefined, }; }) - : null, + : undefined, }; if (!sim.restorePreamble || sim.restorePreamble.transactionData === '') { From 297525ac3bd6c0ff6cb515e8769676bcc17123f0 Mon Sep 17 00:00:00 2001 From: pritsheth Date: Mon, 13 May 2024 09:28:36 -0700 Subject: [PATCH 04/10] Update key type in LedgerEntryDiff --- src/soroban/api.ts | 3 +- src/soroban/parsers.ts | 2 +- test/unit/server/soroban/get_account_test.js | 4 +- test/unit/server/soroban/get_events_test.js | 8 +-- .../server/soroban/get_ledger_entries_test.js | 2 +- .../soroban/simulate_transaction_test.js | 55 ++++++++++--------- 6 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/soroban/api.ts b/src/soroban/api.ts index af73abb61..75f9e4a1c 100644 --- a/src/soroban/api.ts +++ b/src/soroban/api.ts @@ -177,6 +177,7 @@ export namespace Api { interface RawLedgerEntryDiff { type: number; + // This is LedgerKey in base64 key: string; // these are xdr.LedgerEntry in base64 before?: string; @@ -186,7 +187,7 @@ export namespace Api { interface LedgerEntryDiff{ type: number; - key: string; + key: xdr.LedgerKey; before?: xdr.LedgerEntry; after?: xdr.LedgerEntry; } diff --git a/src/soroban/parsers.ts b/src/soroban/parsers.ts index b734632b5..61d5740db 100644 --- a/src/soroban/parsers.ts +++ b/src/soroban/parsers.ts @@ -145,7 +145,7 @@ function parseSuccessful( ? sim.stateDiff!.map((entryDiff) => { return { type: entryDiff.type, - key: entryDiff.key, + key: xdr.LedgerKey.fromXDR(entryDiff.key, 'base64'), before: !!entryDiff.before ? xdr.LedgerEntry.fromXDR(entryDiff.before, 'base64') : undefined, after: !!entryDiff.after ? xdr.LedgerEntry.fromXDR(entryDiff.after, 'base64') : undefined, }; diff --git a/test/unit/server/soroban/get_account_test.js b/test/unit/server/soroban/get_account_test.js index b6781f76c..8258291d3 100644 --- a/test/unit/server/soroban/get_account_test.js +++ b/test/unit/server/soroban/get_account_test.js @@ -25,7 +25,7 @@ describe("Server#getAccount", function () { jsonrpc: "2.0", id: 1, method: "getLedgerEntries", - params: { keys: [ key.toXDR("base64") ] }, + params: { keys: [key.toXDR("base64")] }, }) .returns( Promise.resolve({ @@ -62,7 +62,7 @@ describe("Server#getAccount", function () { jsonrpc: "2.0", id: 1, method: "getLedgerEntries", - params: { keys: [ key.toXDR("base64") ] }, + params: { keys: [key.toXDR("base64")] }, }) .returns( Promise.resolve({ diff --git a/test/unit/server/soroban/get_events_test.js b/test/unit/server/soroban/get_events_test.js index 8b3f4f8e7..f6de7132d 100644 --- a/test/unit/server/soroban/get_events_test.js +++ b/test/unit/server/soroban/get_events_test.js @@ -246,7 +246,7 @@ let getEventsResponseFixture = [ inSuccessfulContractCall: true, topic: topicVals.slice(0, 2), value: eventVal, - txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c" + txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c", }, { type: "contract", @@ -258,7 +258,7 @@ let getEventsResponseFixture = [ inSuccessfulContractCall: true, topic: topicVals.slice(0, 2), value: eventVal, - txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c" + txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c", }, { type: "diagnostic", @@ -270,7 +270,7 @@ let getEventsResponseFixture = [ inSuccessfulContractCall: true, topic: [topicVals[0]], value: eventVal, - txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c" + txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c", }, { type: "contract", @@ -282,6 +282,6 @@ let getEventsResponseFixture = [ inSuccessfulContractCall: true, topic: topicVals, value: eventVal, - txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c" + txHash: "d7d09af2ca4f2929ee701cf86d05e4ca5f849a726d0db344785a8f9894e79e6c", }, ]; diff --git a/test/unit/server/soroban/get_ledger_entries_test.js b/test/unit/server/soroban/get_ledger_entries_test.js index cf11dc5f3..4adda2d3c 100644 --- a/test/unit/server/soroban/get_ledger_entries_test.js +++ b/test/unit/server/soroban/get_ledger_entries_test.js @@ -44,7 +44,7 @@ describe("Server#getLedgerEntries", function () { jsonrpc: "2.0", id: 1, method: "getLedgerEntries", - params: {keys: requests}, + params: { keys: requests }, }) .returns( Promise.resolve({ diff --git a/test/unit/server/soroban/simulate_transaction_test.js b/test/unit/server/soroban/simulate_transaction_test.js index 87f6f8bbe..2bff0ff88 100644 --- a/test/unit/server/soroban/simulate_transaction_test.js +++ b/test/unit/server/soroban/simulate_transaction_test.js @@ -32,18 +32,20 @@ describe("Server#simulateTransaction", async function (done) { retval: xdr.ScVal.fromXDR(simulationResponse.results[0].xdr, "base64"), }, cost: simulationResponse.cost, - stateDiff: [{ - type:1, - key: 'example-key', - before: new xdr.LedgerEntry({ - lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), - }), - after: new xdr.LedgerEntry({ - lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), - }), - }], + stateDiff: [ + { + type: 1, + key: "example-key", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }), + }, + ], _parsed: true, }; @@ -187,7 +189,7 @@ describe("Server#simulateTransaction", async function (done) { delete expected.cost; delete expected.transactionData; delete expected.minResourceFee; - delete expected.stateDiff + delete expected.stateDiff; expected.error = "This is an error"; expected.events = []; @@ -276,19 +278,20 @@ function baseSimulationResponse(results) { cpuInsns: "1", memBytes: "2", }, - stateDiff:[{ - type:1, - key: 'example-key', - before: new xdr.LedgerEntry({ - lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), - }).toXDR('base64'), - after: new xdr.LedgerEntry({ - lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), - }).toXDR('base64'), - }], - + stateDiff: [ + { + type: 1, + key: "example-key", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }).toXDR("base64"), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + ext: new xdr.LedgerEntryExt(0), + }).toXDR("base64"), + }, + ], }; } From 0263f61f78d55462ea9779aa7fcdbcc85ef726bf Mon Sep 17 00:00:00 2001 From: pritsheth Date: Wed, 15 May 2024 11:16:56 -0700 Subject: [PATCH 05/10] Rename stateDiff to stateChanges --- src/soroban/api.ts | 8 ++++---- src/soroban/parsers.ts | 12 ++++++------ .../unit/server/soroban/simulate_transaction_test.js | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/soroban/api.ts b/src/soroban/api.ts index 75f9e4a1c..e270bd066 100644 --- a/src/soroban/api.ts +++ b/src/soroban/api.ts @@ -175,7 +175,7 @@ export namespace Api { value: string; } - interface RawLedgerEntryDiff { + interface RawLedgerEntryChange { type: number; // This is LedgerKey in base64 key: string; @@ -185,7 +185,7 @@ export namespace Api { after?: string; } - interface LedgerEntryDiff{ + interface LedgerEntryChange{ type: number; key: xdr.LedgerKey; before?: xdr.LedgerEntry; @@ -279,7 +279,7 @@ export namespace Api { result?: SimulateHostFunctionResult; // State Difference information - stateDiff?: LedgerEntryDiff[]; + stateChanges?: LedgerEntryChange[]; } /** Includes details about why the simulation failed */ @@ -365,6 +365,6 @@ export namespace Api { }; // State Difference information - stateDiff?: RawLedgerEntryDiff[]; + stateChanges?: RawLedgerEntryChange[]; } } diff --git a/src/soroban/parsers.ts b/src/soroban/parsers.ts index 61d5740db..1900f310d 100644 --- a/src/soroban/parsers.ts +++ b/src/soroban/parsers.ts @@ -141,13 +141,13 @@ function parseSuccessful( })[0] }), - stateDiff: sim.stateDiff?.length ?? 0 > 0 - ? sim.stateDiff!.map((entryDiff) => { + stateChanges: sim.stateChanges?.length ?? 0 > 0 + ? sim.stateChanges!.map((entryChange) => { return { - type: entryDiff.type, - key: xdr.LedgerKey.fromXDR(entryDiff.key, 'base64'), - before: !!entryDiff.before ? xdr.LedgerEntry.fromXDR(entryDiff.before, 'base64') : undefined, - after: !!entryDiff.after ? xdr.LedgerEntry.fromXDR(entryDiff.after, 'base64') : undefined, + type: entryChange.type, + key: xdr.LedgerKey.fromXDR(entryChange.key, 'base64'), + before: !!entryChange.before ? xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : undefined, + after: !!entryChange.after ? xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : undefined, }; }) : undefined, diff --git a/test/unit/server/soroban/simulate_transaction_test.js b/test/unit/server/soroban/simulate_transaction_test.js index 2bff0ff88..5abe52fb5 100644 --- a/test/unit/server/soroban/simulate_transaction_test.js +++ b/test/unit/server/soroban/simulate_transaction_test.js @@ -32,7 +32,7 @@ describe("Server#simulateTransaction", async function (done) { retval: xdr.ScVal.fromXDR(simulationResponse.results[0].xdr, "base64"), }, cost: simulationResponse.cost, - stateDiff: [ + stateChanges: [ { type: 1, key: "example-key", @@ -189,7 +189,7 @@ describe("Server#simulateTransaction", async function (done) { delete expected.cost; delete expected.transactionData; delete expected.minResourceFee; - delete expected.stateDiff; + delete expected.stateChanges; expected.error = "This is an error"; expected.events = []; @@ -215,7 +215,7 @@ function cloneSimulation(sim) { retval: xdr.ScVal.fromXDR(sim.result.retval.toXDR()), }, cost: sim.cost, - stateDiff: sim.stateDiff, + stateChanges: sim.stateChanges, _parsed: sim._parsed, }; } @@ -278,7 +278,7 @@ function baseSimulationResponse(results) { cpuInsns: "1", memBytes: "2", }, - stateDiff: [ + stateChanges: [ { type: 1, key: "example-key", From 07e4c610980ed8f0b1b3c4c692f50c58b5aa817e Mon Sep 17 00:00:00 2001 From: Prit Sheth Date: Fri, 17 May 2024 00:06:59 -0700 Subject: [PATCH 06/10] Fix review comments and add more tests --- src/soroban/api.ts | 40 +++---- src/soroban/parsers.ts | 6 +- .../soroban/simulate_transaction_test.js | 112 ++++++++++++++++-- 3 files changed, 123 insertions(+), 35 deletions(-) diff --git a/src/soroban/api.ts b/src/soroban/api.ts index e270bd066..f9dabc306 100644 --- a/src/soroban/api.ts +++ b/src/soroban/api.ts @@ -3,13 +3,6 @@ import { AssetType, Contract, SorobanDataBuilder, xdr } from '@stellar/stellar-b /* tslint:disable-next-line:no-namespace */ /** @namespace Api */ export namespace Api { - export interface Balance { - asset_type: AssetType.credit4 | AssetType.credit12; - asset_code: string; - asset_issuer: string; - classic: string; - smart: string; - } export interface Cost { cpuInsns: string; @@ -175,21 +168,21 @@ export namespace Api { value: string; } - interface RawLedgerEntryChange { + export interface RawLedgerEntryChange { type: number; - // This is LedgerKey in base64 + /** This is LedgerKey in base64 */ key: string; - // these are xdr.LedgerEntry in base64 - before?: string; - // these are xdr.LedgerEntry in base64 - after?: string; + /** This is xdr.LedgerEntry in base64 */ + before: string | null; + /** This is xdr.LedgerEntry in base64 */ + after: string | null; } - interface LedgerEntryChange{ + export interface LedgerEntryChange{ type: number; key: xdr.LedgerKey; - before?: xdr.LedgerEntry; - after?: xdr.LedgerEntry; + before: xdr.LedgerEntry | null; + after: xdr.LedgerEntry | null; } export type SendTransactionStatus = @@ -278,7 +271,7 @@ export namespace Api { /** present only for invocation simulation */ result?: SimulateHostFunctionResult; - // State Difference information + /** State Difference information */ stateChanges?: LedgerEntryChange[]; } @@ -349,22 +342,23 @@ export namespace Api { id: string; latestLedger: number; error?: string; - // this is an xdr.SorobanTransactionData in base64 + /** This is an xdr.SorobanTransactionData in base64 */ transactionData?: string; - // these are xdr.DiagnosticEvents in base64 + /** These are xdr.DiagnosticEvents in base64 */ events?: string[]; minResourceFee?: string; - // This will only contain a single element if present, because only a single - // invokeHostFunctionOperation is supported per transaction. + /** This will only contain a single element if present, because only a single + * invokeHostFunctionOperation is supported per transaction. + * */ results?: RawSimulateHostFunctionResult[]; cost?: Cost; - // present if succeeded but has expired ledger entries + /** Present if succeeded but has expired ledger entries */ restorePreamble?: { minResourceFee: string; transactionData: string; }; - // State Difference information + /** State Difference information */ stateChanges?: RawLedgerEntryChange[]; } } diff --git a/src/soroban/parsers.ts b/src/soroban/parsers.ts index 1900f310d..1838556ab 100644 --- a/src/soroban/parsers.ts +++ b/src/soroban/parsers.ts @@ -142,12 +142,12 @@ function parseSuccessful( }), stateChanges: sim.stateChanges?.length ?? 0 > 0 - ? sim.stateChanges!.map((entryChange) => { + ? sim.stateChanges.map((entryChange) => { return { type: entryChange.type, key: xdr.LedgerKey.fromXDR(entryChange.key, 'base64'), - before: !!entryChange.before ? xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : undefined, - after: !!entryChange.after ? xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : undefined, + before: entryChange.before ? xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : null, + after: entryChange.after ? xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : null, }; }) : undefined, diff --git a/test/unit/server/soroban/simulate_transaction_test.js b/test/unit/server/soroban/simulate_transaction_test.js index 5abe52fb5..68e2b7dbc 100644 --- a/test/unit/server/soroban/simulate_transaction_test.js +++ b/test/unit/server/soroban/simulate_transaction_test.js @@ -34,15 +34,17 @@ describe("Server#simulateTransaction", async function (done) { cost: simulationResponse.cost, stateChanges: [ { - type: 1, - key: "example-key", + type: 2, + key: "example-key-2", before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), }), after: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), }), }, ], @@ -180,6 +182,53 @@ describe("Server#simulateTransaction", async function (done) { ); }); + it("works with state changes", async function () { + return invokeSimulationResponseWithStateChanges(address).then( + (simResponse) => { + const expected = cloneSimulation(parsedSimulationResponse); + expected.stateChanges = [ + { + type: 2, + key: "example-key-2", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }), + }, + { + type: 1, + key: "example-key-1", + before: null, + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }), + }, + { + type: 3, + key: "example-key-3", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }), + after: null, + }, + ] + + const parsed = parseRawSimulation(simResponse); + expect(parsed).to.be.deep.equal(expected); + }, + ); + }); + it("works with errors", function () { let simResponse = simulationResponseError(); @@ -280,17 +329,19 @@ function baseSimulationResponse(results) { }, stateChanges: [ { - type: 1, - key: "example-key", + type: 2, + key: "example-key-2", before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), }).toXDR("base64"), after: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, - ext: new xdr.LedgerEntryExt(0), + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), }).toXDR("base64"), - }, + } ], }; } @@ -305,6 +356,49 @@ async function invokeSimulationResponseWithRestoration(address) { }; } +async function invokeSimulationResponseWithStateChanges(address) { + return { + ...(await invokeSimulationResponse(address)), + stateChanges: [ + { + type: 2, + key: "example-key-2", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }).toXDR("base64"), + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }).toXDR("base64"), + }, + { + type: 1, + key: "example-key-1", + before: null, + after: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }).toXDR("base64"), + }, + { + type: 3, + key: "example-key-3", + before: new xdr.LedgerEntry({ + lastModifiedLedgerSeq: 0, + data: new xdr.LedgerEntryData(), + ext: new xdr.LedgerEntryExt(), + }).toXDR("base64"), + after: null, + }, + ], + }; +} + + describe("works with real responses", function () { const schema = { transactionData: From 010bf92770b665097ccfbb0b9d918005f7c1be31 Mon Sep 17 00:00:00 2001 From: Prit Sheth Date: Fri, 17 May 2024 13:50:52 -0700 Subject: [PATCH 07/10] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3de9988b..067519b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ A breaking change will get clearly marked in this log. ## Unreleased +Added: + +- Add stateChanges in SimulateTransaction API response ([#963](https://github.com/stellar/js-stellar-sdk/pull/963)) + ## [v12.0.0](https://github.com/stellar/js-stellar-sdk/compare/v11.3.0...v12.0.0) From 7698a58d43ef4cdec6e7252635e111d1c4b8675f Mon Sep 17 00:00:00 2001 From: Prit Sheth Date: Fri, 17 May 2024 13:57:43 -0700 Subject: [PATCH 08/10] Fix tests --- src/rpc/api.ts | 2 +- src/rpc/parsers.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/api.ts b/src/rpc/api.ts index f9dabc306..cbfb8e442 100644 --- a/src/rpc/api.ts +++ b/src/rpc/api.ts @@ -1,4 +1,4 @@ -import { AssetType, Contract, SorobanDataBuilder, xdr } from '@stellar/stellar-base'; +import { Contract, SorobanDataBuilder, xdr } from '@stellar/stellar-base'; /* tslint:disable-next-line:no-namespace */ /** @namespace Api */ diff --git a/src/rpc/parsers.ts b/src/rpc/parsers.ts index 1838556ab..16be6fa71 100644 --- a/src/rpc/parsers.ts +++ b/src/rpc/parsers.ts @@ -142,7 +142,7 @@ function parseSuccessful( }), stateChanges: sim.stateChanges?.length ?? 0 > 0 - ? sim.stateChanges.map((entryChange) => { + ? sim.stateChanges?.map((entryChange) => { return { type: entryChange.type, key: xdr.LedgerKey.fromXDR(entryChange.key, 'base64'), From 47272499235c161158ef80eb9d663f0665655701 Mon Sep 17 00:00:00 2001 From: Prit Sheth Date: Wed, 29 May 2024 13:01:02 -0700 Subject: [PATCH 09/10] Fix review comments --- CHANGELOG.md | 16 ++++++- src/rpc/api.ts | 2 +- .../soroban/simulate_transaction_test.js | 45 +++++++++++++++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a491aad86..9176304d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,23 @@ A breaking change will get clearly marked in this log. Added: -- Add stateChanges in SimulateTransaction API response ([#963](https://github.com/stellar/js-stellar-sdk/pull/963)) +- `rpc.server.simulateTransaction` now supports optional stateChanges as mentioned below ([#963](https://github.com/stellar/js-stellar-sdk/pull/963)) +- If `Before` is omitted, it constitutes a creation, if `After` is omitted, it constitutes a deletions, note that `Before` and `After` cannot be be omitted at the same time. +``` +/** State Difference information */ + stateChanges?: LedgerEntryChange[]; + +interface LedgerEntryChange{ + type: number; + key: xdr.LedgerKey; + before: xdr.LedgerEntry | null; + after: xdr.LedgerEntry | null; + } + +``` + ## [v12.0.0-rc.3](https://github.com/stellar/js-stellar-sdk/compare/v11.3.0...v12.0.0-rc.3) ### Breaking Changes diff --git a/src/rpc/api.ts b/src/rpc/api.ts index cbfb8e442..0ec813c08 100644 --- a/src/rpc/api.ts +++ b/src/rpc/api.ts @@ -168,7 +168,7 @@ export namespace Api { value: string; } - export interface RawLedgerEntryChange { + interface RawLedgerEntryChange { type: number; /** This is LedgerKey in base64 */ key: string; diff --git a/test/unit/server/soroban/simulate_transaction_test.js b/test/unit/server/soroban/simulate_transaction_test.js index 55de24a89..863ad6b13 100644 --- a/test/unit/server/soroban/simulate_transaction_test.js +++ b/test/unit/server/soroban/simulate_transaction_test.js @@ -18,6 +18,14 @@ describe("Server#simulateTransaction", async function (done) { let contract = new StellarSdk.Contract(contractId); let address = contract.address().toScAddress(); + const accountId = + "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"; + const accountKey = xdr.LedgerKey.account( + new xdr.LedgerKeyAccount({ + accountId: Keypair.fromPublicKey(accountId).xdrPublicKey(), + }), + ); + const simulationResponse = await invokeSimulationResponse(address); const parsedSimulationResponse = { id: simulationResponse.id, @@ -35,7 +43,7 @@ describe("Server#simulateTransaction", async function (done) { stateChanges: [ { type: 2, - key: "example-key-2", + key: accountKey, before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), @@ -189,7 +197,7 @@ describe("Server#simulateTransaction", async function (done) { expected.stateChanges = [ { type: 2, - key: "example-key-2", + key: accountKey, before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), @@ -203,7 +211,7 @@ describe("Server#simulateTransaction", async function (done) { }, { type: 1, - key: "example-key-1", + key: accountKey, before: null, after: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, @@ -213,7 +221,7 @@ describe("Server#simulateTransaction", async function (done) { }, { type: 3, - key: "example-key-3", + key: accountKey, before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), @@ -316,6 +324,8 @@ function simulationResponseError(events) { } function baseSimulationResponse(results) { + const accountId = "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"; + return { id: 1, events: [], @@ -330,7 +340,11 @@ function baseSimulationResponse(results) { stateChanges: [ { type: 2, - key: "example-key-2", + key: xdr.LedgerKey.account( + new xdr.LedgerKeyAccount({ + accountId: Keypair.fromPublicKey(accountId).xdrPublicKey(), + }), + ).toXDR("base64"), before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), @@ -357,12 +371,19 @@ async function invokeSimulationResponseWithRestoration(address) { } async function invokeSimulationResponseWithStateChanges(address) { + const accountId = "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"; + return { + ...(await invokeSimulationResponse(address)), stateChanges: [ { type: 2, - key: "example-key-2", + key: xdr.LedgerKey.account( + new xdr.LedgerKeyAccount({ + accountId: Keypair.fromPublicKey(accountId).xdrPublicKey(), + }), + ).toXDR("base64"), before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), @@ -376,7 +397,11 @@ async function invokeSimulationResponseWithStateChanges(address) { }, { type: 1, - key: "example-key-1", + key: xdr.LedgerKey.account( + new xdr.LedgerKeyAccount({ + accountId: Keypair.fromPublicKey(accountId).xdrPublicKey(), + }), + ).toXDR("base64"), before: null, after: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, @@ -386,7 +411,11 @@ async function invokeSimulationResponseWithStateChanges(address) { }, { type: 3, - key: "example-key-3", + key: xdr.LedgerKey.account( + new xdr.LedgerKeyAccount({ + accountId: Keypair.fromPublicKey(accountId).xdrPublicKey(), + }), + ).toXDR("base64"), before: new xdr.LedgerEntry({ lastModifiedLedgerSeq: 0, data: new xdr.LedgerEntryData(), From c577557838131033201c01aa8354c61583fccccb Mon Sep 17 00:00:00 2001 From: Prit Sheth Date: Thu, 30 May 2024 14:57:04 -0700 Subject: [PATCH 10/10] Use spread operator --- src/rpc/api.ts | 2 +- src/rpc/parsers.ts | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/rpc/api.ts b/src/rpc/api.ts index 0ec813c08..25591b379 100644 --- a/src/rpc/api.ts +++ b/src/rpc/api.ts @@ -178,7 +178,7 @@ export namespace Api { after: string | null; } - export interface LedgerEntryChange{ + export interface LedgerEntryChange { type: number; key: xdr.LedgerKey; before: xdr.LedgerEntry | null; diff --git a/src/rpc/parsers.ts b/src/rpc/parsers.ts index 16be6fa71..a54a83434 100644 --- a/src/rpc/parsers.ts +++ b/src/rpc/parsers.ts @@ -141,16 +141,17 @@ function parseSuccessful( })[0] }), - stateChanges: sim.stateChanges?.length ?? 0 > 0 - ? sim.stateChanges?.map((entryChange) => { - return { - type: entryChange.type, - key: xdr.LedgerKey.fromXDR(entryChange.key, 'base64'), - before: entryChange.before ? xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : null, - after: entryChange.after ? xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : null, - }; - }) - : undefined, + ...(sim.stateChanges?.length ?? 0 > 0) && { + stateChanges: sim.stateChanges?.map((entryChange) => { + return { + type: entryChange.type, + key: xdr.LedgerKey.fromXDR(entryChange.key, 'base64'), + before: entryChange.before ? xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : null, + after: entryChange.after ? xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : null, + }; + }) + } + }; if (!sim.restorePreamble || sim.restorePreamble.transactionData === '') {