Source

lib/rpc/parsers.js

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.parseRawEvents = parseRawEvents;
  6. exports.parseRawLedgerEntries = parseRawLedgerEntries;
  7. exports.parseRawSendTransaction = parseRawSendTransaction;
  8. exports.parseRawSimulation = parseRawSimulation;
  9. exports.parseRawTransactions = parseRawTransactions;
  10. exports.parseTransactionInfo = parseTransactionInfo;
  11. var _stellarBase = require("@stellar/stellar-base");
  12. var _api = require("./api");
  13. /**
  14. * Parse the response from invoking the `submitTransaction` method of a Soroban RPC server.
  15. * @memberof module:rpc
  16. * @private
  17. *
  18. * @param {Api.RawSendTransactionResponse} raw the raw `submitTransaction` response from the Soroban RPC server to parse
  19. * @returns {Api.SendTransactionResponse} transaction response parsed from the Soroban RPC server's response
  20. */
  21. function parseRawSendTransaction(raw) {
  22. const {
  23. errorResultXdr,
  24. diagnosticEventsXdr
  25. } = raw;
  26. delete raw.errorResultXdr;
  27. delete raw.diagnosticEventsXdr;
  28. if (errorResultXdr) {
  29. return {
  30. ...raw,
  31. ...(diagnosticEventsXdr !== undefined && diagnosticEventsXdr.length > 0 && {
  32. diagnosticEvents: diagnosticEventsXdr.map(evt => _stellarBase.xdr.DiagnosticEvent.fromXDR(evt, 'base64'))
  33. }),
  34. errorResult: _stellarBase.xdr.TransactionResult.fromXDR(errorResultXdr, 'base64')
  35. };
  36. }
  37. return {
  38. ...raw
  39. };
  40. }
  41. function parseTransactionInfo(raw) {
  42. const meta = _stellarBase.xdr.TransactionMeta.fromXDR(raw.resultMetaXdr, 'base64');
  43. const info = {
  44. ledger: raw.ledger,
  45. createdAt: raw.createdAt,
  46. applicationOrder: raw.applicationOrder,
  47. feeBump: raw.feeBump,
  48. envelopeXdr: _stellarBase.xdr.TransactionEnvelope.fromXDR(raw.envelopeXdr, 'base64'),
  49. resultXdr: _stellarBase.xdr.TransactionResult.fromXDR(raw.resultXdr, 'base64'),
  50. resultMetaXdr: meta
  51. };
  52. if (meta.switch() === 3 && meta.v3().sorobanMeta() !== null) {
  53. info.returnValue = meta.v3().sorobanMeta()?.returnValue();
  54. }
  55. if ('diagnosticEventsXdr' in raw && raw.diagnosticEventsXdr) {
  56. info.diagnosticEventsXdr = raw.diagnosticEventsXdr.map(diagnosticEvent => _stellarBase.xdr.DiagnosticEvent.fromXDR(diagnosticEvent, 'base64'));
  57. }
  58. return info;
  59. }
  60. function parseRawTransactions(r) {
  61. return {
  62. status: r.status,
  63. txHash: r.txHash,
  64. ...parseTransactionInfo(r)
  65. };
  66. }
  67. /**
  68. * Parse and return the retrieved events, if any, from a raw response from a Soroban RPC server.
  69. * @memberof module:rpc
  70. *
  71. * @param {Api.RawGetEventsResponse} raw the raw `getEvents` response from the Soroban RPC server to parse
  72. * @returns {Api.GetEventsResponse} events parsed from the Soroban RPC server's response
  73. */
  74. function parseRawEvents(raw) {
  75. return {
  76. latestLedger: raw.latestLedger,
  77. cursor: raw.cursor,
  78. events: (raw.events ?? []).map(evt => {
  79. const clone = {
  80. ...evt
  81. };
  82. delete clone.contractId; // `as any` hack because contractId field isn't optional
  83. // the contractId may be empty so we omit the field in that case
  84. return {
  85. ...clone,
  86. ...(evt.contractId !== '' && {
  87. contractId: new _stellarBase.Contract(evt.contractId)
  88. }),
  89. topic: evt.topic.map(topic => _stellarBase.xdr.ScVal.fromXDR(topic, 'base64')),
  90. value: _stellarBase.xdr.ScVal.fromXDR(evt.value, 'base64')
  91. };
  92. })
  93. };
  94. }
  95. /**
  96. * Parse and return the retrieved ledger entries, if any, from a raw response from a Soroban RPC server.
  97. * @memberof module:rpc
  98. * @private
  99. *
  100. * @param {Api.RawGetLedgerEntriesResponse} raw he raw `getLedgerEntries` response from the Soroban RPC server to parse
  101. * @returns {Api.GetLedgerEntriesResponse} ledger entries parsed from the Soroban RPC server's response
  102. */
  103. function parseRawLedgerEntries(raw) {
  104. return {
  105. latestLedger: raw.latestLedger,
  106. entries: (raw.entries ?? []).map(rawEntry => {
  107. if (!rawEntry.key || !rawEntry.xdr) {
  108. throw new TypeError(`invalid ledger entry: ${JSON.stringify(rawEntry)}`);
  109. }
  110. return {
  111. lastModifiedLedgerSeq: rawEntry.lastModifiedLedgerSeq,
  112. key: _stellarBase.xdr.LedgerKey.fromXDR(rawEntry.key, 'base64'),
  113. val: _stellarBase.xdr.LedgerEntryData.fromXDR(rawEntry.xdr, 'base64'),
  114. ...(rawEntry.liveUntilLedgerSeq !== undefined && {
  115. liveUntilLedgerSeq: rawEntry.liveUntilLedgerSeq
  116. })
  117. };
  118. })
  119. };
  120. }
  121. /**
  122. * Parse whether or not the transaction simulation was successful, returning the relevant response.
  123. * @memberof module:rpc
  124. * @private
  125. *
  126. * @param {Api.RawSimulateTransactionResponse} sim a raw response from the `simulateTransaction` method of the Soroban RPC server to parse
  127. * @param {Api.BaseSimulateTransactionResponse} partial a partially built simulate transaction response that will be used to build the return response
  128. * @returns {Api.SimulateTransactionRestoreResponse | Api.SimulateTransactionSuccessResponse} Either a simulation response indicating what ledger entries should be restored, or if the simulation was successful.
  129. */
  130. function parseSuccessful(sim, partial) {
  131. // success type: might have a result (if invoking) and...
  132. const success = {
  133. ...partial,
  134. transactionData: new _stellarBase.SorobanDataBuilder(sim.transactionData),
  135. minResourceFee: sim.minResourceFee,
  136. // coalesce 0-or-1-element results[] list into a single result struct
  137. // with decoded fields if present
  138. // eslint-disable-next-line no-self-compare
  139. ...((sim.results?.length ?? 0 > 0) && {
  140. result: sim.results.map(row => ({
  141. auth: (row.auth ?? []).map(entry => _stellarBase.xdr.SorobanAuthorizationEntry.fromXDR(entry, 'base64')),
  142. // if return value is missing ("falsy") we coalesce to void
  143. retval: row.xdr ? _stellarBase.xdr.ScVal.fromXDR(row.xdr, 'base64') : _stellarBase.xdr.ScVal.scvVoid()
  144. }))[0]
  145. }),
  146. // eslint-disable-next-line no-self-compare
  147. ...((sim.stateChanges?.length ?? 0 > 0) && {
  148. stateChanges: sim.stateChanges?.map(entryChange => ({
  149. type: entryChange.type,
  150. key: _stellarBase.xdr.LedgerKey.fromXDR(entryChange.key, 'base64'),
  151. before: entryChange.before ? _stellarBase.xdr.LedgerEntry.fromXDR(entryChange.before, 'base64') : null,
  152. after: entryChange.after ? _stellarBase.xdr.LedgerEntry.fromXDR(entryChange.after, 'base64') : null
  153. }))
  154. })
  155. };
  156. if (!sim.restorePreamble || sim.restorePreamble.transactionData === '') {
  157. return success;
  158. }
  159. // ...might have a restoration hint (if some state is expired)
  160. return {
  161. ...success,
  162. restorePreamble: {
  163. minResourceFee: sim.restorePreamble.minResourceFee,
  164. transactionData: new _stellarBase.SorobanDataBuilder(sim.restorePreamble.transactionData)
  165. }
  166. };
  167. }
  168. /**
  169. * Converts a raw response schema into one with parsed XDR fields and a simplified interface.
  170. * @warning This API is only exported for testing purposes and should not be relied on or considered "stable".
  171. * @memberof module:rpc
  172. *
  173. * @param {Api.SimulateTransactionResponse | Api.RawSimulateTransactionResponse} sim the raw response schema (parsed ones are allowed, best-effort
  174. * detected, and returned untouched)
  175. * @returns {Api.SimulateTransactionResponse} the original parameter (if already parsed), parsed otherwise
  176. */
  177. function parseRawSimulation(sim) {
  178. const looksRaw = _api.Api.isSimulationRaw(sim);
  179. if (!looksRaw) {
  180. // Gordon Ramsey in shambles
  181. return sim;
  182. }
  183. // shared across all responses
  184. const base = {
  185. _parsed: true,
  186. id: sim.id,
  187. latestLedger: sim.latestLedger,
  188. events: sim.events?.map(evt => _stellarBase.xdr.DiagnosticEvent.fromXDR(evt, 'base64')) ?? []
  189. };
  190. // error type: just has error string
  191. if (typeof sim.error === 'string') {
  192. return {
  193. ...base,
  194. error: sim.error
  195. };
  196. }
  197. return parseSuccessful(sim, base);
  198. }