diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3d33badb..0e7a4e7c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,9 @@ jobs: # Workaround for some `yarn` nonsense, see: # https://github.com/yarnpkg/yarn/issues/6312#issuecomment-429685210 - name: Install Dependencies - run: yarn install --network-concurrency 1 + run: | + yarn cache clean + yarn install --network-concurrency 1 - name: Build run: yarn build:prod diff --git a/CHANGELOG.md b/CHANGELOG.md index f7753087..539337a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ A breaking change should be clearly marked in this log. +#### Pending +updated prepare transaction for new soroban simulation results and fees [#76](https://github.com/stellar/js-soroban-client/issues/76) + + #### 0.5.1 * remove params from jsonrpc post payload if empty. [#70](https://github.com/stellar/js-soroban-client/pull/70) diff --git a/package.json b/package.json index bc7e2dd3..9d5a48f1 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "eventsource": "^2.0.2", "lodash": "^4.17.21", "randombytes": "^2.1.0", - "stellar-base": "v8.2.2-soroban.12", + "stellar-base": "^9.0.0-soroban.1", "toml": "^3.0.0", "urijs": "^1.19.1" } diff --git a/src/server.ts b/src/server.ts index 25249d24..397426f5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -372,8 +372,19 @@ export class Server { } /** - * Submit a trial contract invocation, then add the expected ledger footprint - * and auth into the transaction so it is ready for signing & sending. + * Submit a trial contract invocation, first run a simulation of the contract + * invocation as defined on the incoming transaction, and apply the results + * to a new copy of the transaction which is then returned. Setting the ledger + * footprint and authorization, so the resulting transaction is ready for signing & sending. + * + * The returned transaction will also have an updated fee that is the sum of fee set + * on incoming transaction with the contract resource fees estimated from simulation. It is + * adviseable to check the fee on returned transaction and validate or take appropriate + * measures for interaction with user to confirm it is acceptable. + * + * You can call the {simulateTransaction(transaction)} method directly first if you + * want to inspect estimated fees for a given transaction in detail first if that is + * of importance. * * @example * const contractId = '0000000000000000000000000000000000000000000000000000000000000001'; @@ -419,25 +430,29 @@ export class Server { * passphrase. If not passed, the current network passphrase will be requested * from the server via `getNetwork`. * @returns {Promise} Returns a copy of the - * transaction, with the expected ledger footprint added. + * transaction, with the expected ledger footprint and authorizations added + * and the transaction fee will automatically be adjusted to the sum of + * the incoming transaction fee and the contract minimum resource fees + * discovered from the simulation, + * */ public async prepareTransaction( transaction: Transaction | FeeBumpTransaction, networkPassphrase?: string, ): Promise { - const [{ passphrase }, { error, results }] = await Promise.all([ + const [{ passphrase }, simResponse] = await Promise.all([ networkPassphrase ? Promise.resolve({ passphrase: networkPassphrase }) : this.getNetwork(), this.simulateTransaction(transaction), ]); - if (error) { - throw error; + if (simResponse.error) { + throw simResponse.error; } - if (!results) { + if (!simResponse.results || simResponse.results.length < 1) { throw new Error("transaction simulation failed"); } - return assembleTransaction(transaction, passphrase, results); + return assembleTransaction(transaction, passphrase, simResponse); } /** diff --git a/src/soroban_rpc.ts b/src/soroban_rpc.ts index fac59bd4..fb9fadcc 100644 --- a/src/soroban_rpc.ts +++ b/src/soroban_rpc.ts @@ -112,16 +112,22 @@ export namespace SorobanRpc { latestLedgerCloseTime: number; } + export interface SimulateHostFunctionResult { + // each string is ContractAuth XDR in base64 + auth: string[]; + // function response as SCVal XDR in base64 + xdr: string; + } + export interface SimulateTransactionResponse { id: string; - cost: Cost; - results?: Array<{ - xdr: string; - footprint: string; - auth: string[]; - events: string[]; - }>; error?: jsonrpc.Error; + // this is SorobanTransactionData XDR in base64 + transactionData: string; + events: string[]; + minResourceFee: string; + results: SimulateHostFunctionResult[]; latestLedger: number; + cost: Cost; } } diff --git a/src/transaction.ts b/src/transaction.ts index 53591e50..c304de78 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -6,35 +6,56 @@ import { TransactionBuilder, xdr, } from "stellar-base"; +import { SorobanRpc } from "./soroban_rpc"; // TODO: Transaction is immutable, so we need to re-build it here. :( export function assembleTransaction( raw: Transaction | FeeBumpTransaction, networkPassphrase: string, - simulated: Array; - }>, + simulation: SorobanRpc.SimulateTransactionResponse, ): Transaction { if ("innerTransaction" in raw) { // TODO: Handle feebump transactions return assembleTransaction( raw.innerTransaction, networkPassphrase, - simulated, + simulation, ); } - if (simulated.length !== raw.operations.length) { + if ( + raw.operations.length !== 1 || + raw.operations[0].type !== "invokeHostFunction" + ) { throw new Error( - "number of simulated operations not equal to number of transaction operations", + "unsupported operation type, must be only one InvokeHostFunctionOp in the transaction.", + ); + } + + const rawInvokeHostFunctionOp: any = raw.operations[0]; + + if ( + !rawInvokeHostFunctionOp.functions || + !simulation.results || + rawInvokeHostFunctionOp.functions.length !== simulation.results.length + ) { + throw new Error( + "preflight simulation results do not contain same count of HostFunctions that InvokeHostFunctionOp in the transaction has.", ); } - // TODO: Figure out a cleaner way to clone this transaction. const source = new Account(raw.source, `${parseInt(raw.sequence, 10) - 1}`); - const txn = new TransactionBuilder(source, { - fee: raw.fee, + const classicFeeNum = parseInt(raw.fee, 10) || 0; + const minResourceFeeNum = parseInt(simulation.minResourceFee, 10) || 0; + const txnBuilder = new TransactionBuilder(source, { + // automatically update the tx fee that will be set on the resulting tx + // to the sum of 'classic' fee provided from incoming tx.fee + // and minResourceFee provided by simulation. + // + // 'classic' tx fees are measured as the product of tx.fee * 'number of operations', In soroban contract tx, + // there can only be single operation in the tx, so can make simplification + // of total classic fees for the soroban transaction will be equal to incoming tx.fee + minResourceFee. + fee: (classicFeeNum + minResourceFeeNum).toString(), memo: raw.memo, networkPassphrase, timebounds: raw.timeBounds, @@ -44,35 +65,37 @@ export function assembleTransaction( minAccountSequenceLedgerGap: raw.minAccountSequenceLedgerGap, extraSigners: raw.extraSigners, }); - for (let i = 0; i < raw.operations.length; i++) { - const rawOp = raw.operations[i]; - if ("function" in rawOp) { - const sim = simulated[i]; - if (!sim) { - throw new Error("missing simulated operation"); - } - let footprint = sim.footprint ?? rawOp.footprint; - if (!(footprint instanceof xdr.LedgerFootprint)) { - footprint = xdr.LedgerFootprint.fromXDR(footprint.toString(), "base64"); - } - const auth = (sim.auth ?? rawOp.auth).map((a) => - a instanceof xdr.ContractAuth - ? a - : xdr.ContractAuth.fromXDR(a.toString(), "base64"), - ); - // TODO: Figure out a cleaner way to clone these operations - txn.addOperation( - Operation.invokeHostFunction({ - function: rawOp.function, - parameters: rawOp.parameters, - footprint, - auth, - }), - ); - } else { - // TODO: Handle this. - throw new Error("Unsupported operation type"); - } + + // apply the pre-built Auth from simulation onto each Tx/Op/HostFunction + // invocation + const authDecoratedHostFunctions = simulation.results.map( + (functionSimulationResult, i) => { + const hostFn: xdr.HostFunction = rawInvokeHostFunctionOp.functions[i]; + hostFn.auth(buildContractAuth(functionSimulationResult.auth)); + return hostFn; + }, + ); + + txnBuilder.addOperation( + Operation.invokeHostFunctions({ + functions: authDecoratedHostFunctions, + }), + ); + + // apply the pre-built Soroban Tx Data from simulation onto the Tx + const sorobanTxData = xdr.SorobanTransactionData.fromXDR( + simulation.transactionData, + "base64", + ); + txnBuilder.setSorobanData(sorobanTxData); + + return txnBuilder.build(); +} + +function buildContractAuth(auths: string[]): xdr.ContractAuth[] { + const contractAuths: xdr.ContractAuth[] = []; + for (const authStr of auths) { + contractAuths.push(xdr.ContractAuth.fromXDR(authStr, "base64")); } - return txn.build(); + return contractAuths; } diff --git a/test/unit/server/simulate_transaction_test.js b/test/unit/server/simulate_transaction_test.js index 88367d4f..95fac011 100644 --- a/test/unit/server/simulate_transaction_test.js +++ b/test/unit/server/simulate_transaction_test.js @@ -5,24 +5,75 @@ describe("Server#simulateTransaction", function () { "56199647068161" ); - beforeEach(function () { + const simulationResponse = { + transactionData: new SorobanClient.xdr.SorobanTransactionData({ + resources: new SorobanClient.xdr.SorobanResources({ + footprint: new SorobanClient.xdr.LedgerFootprint({ + readOnly: [], + readWrite: [], + }), + instructions: 0, + readBytes: 0, + writeBytes: 0, + extendedMetaDataSizeBytes: 0, + }), + refundableFee: SorobanClient.xdr.Int64.fromString("0"), + ext: new SorobanClient.xdr.ExtensionPoint(0), + }).toXDR("base64"), + events: [], + minResourceFee: "15", + results: [ + { + auth: [ + new SorobanClient.xdr.ContractAuth({ + addressWithNonce: null, + rootInvocation: new SorobanClient.xdr.AuthorizedInvocation({ + contractId: Buffer.alloc(32), + functionName: "fn", + args: [], + subInvocations: [], + }), + signatureArgs: [], + }).toXDR("base64"), + ], + xdr: SorobanClient.xdr.ScVal.scvU32(0) + .toXDR() + .toString("base64"), + }, + ], + latestLedger: 3, + cost: { + cpuInsns: "0", + memBytes: "0", + }, + }; + + beforeEach(function() { this.server = new SorobanClient.Server(serverUrl); this.axiosMock = sinon.mock(AxiosClient); - let transaction = new SorobanClient.TransactionBuilder(account, { - fee: 100, - networkPassphrase: SorobanClient.Networks.TESTNET, - v1: true, - }) - .addOperation( - SorobanClient.Operation.payment({ - destination: - "GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW", - asset: SorobanClient.Asset.native(), - amount: "100.50", - }) - ) - .setTimeout(SorobanClient.TimeoutInfinite) - .build(); + const source = new SorobanClient.Account( + "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI", + "1", + ); + function emptyContractTransaction() { + return new SorobanClient.TransactionBuilder(source, { + fee: 100, + networkPassphrase: "Test", + v1: true, + }) + .addOperation( + SorobanClient.Operation.invokeHostFunction({ + args: new SorobanClient.xdr.HostFunctionArgs.hostFunctionTypeInvokeContract( + [], + ), + auth: [], + }), + ) + .setTimeout(SorobanClient.TimeoutInfinite) + .build(); + } + + const transaction = emptyContractTransaction(); transaction.sign(keypair); this.transaction = transaction; @@ -35,25 +86,7 @@ describe("Server#simulateTransaction", function () { this.axiosMock.restore(); }); - const result = { - cost: { - cpuInsns: "10000", - memBytes: "10000", - }, - results: [ - { - xdr: SorobanClient.xdr.ScVal.scvU32(0).toXDR().toString("base64"), - footprint: new SorobanClient.xdr.LedgerFootprint({ - readOnly: [], - readWrite: [], - }).toXDR("base64"), - events: [], - }, - ], - latestLedger: 1, - }; - - it("simulates a transaction", function (done) { + it("simulates a transaction", function(done) { this.axiosMock .expects("post") .withArgs(serverUrl, { @@ -62,12 +95,14 @@ describe("Server#simulateTransaction", function () { method: "simulateTransaction", params: [this.blob], }) - .returns(Promise.resolve({ data: { id: 1, result } })); + .returns( + Promise.resolve({ data: { id: 1, result: simulationResponse } }), + ); this.server .simulateTransaction(this.transaction) - .then(function (response) { - expect(response).to.be.deep.equal(result); + .then(function(response) { + expect(response).to.be.deep.equal(simulationResponse); done(); }) .catch(function (err) { diff --git a/test/unit/transaction_test.js b/test/unit/transaction_test.js index ac98710a..95e25895 100644 --- a/test/unit/transaction_test.js +++ b/test/unit/transaction_test.js @@ -1,31 +1,79 @@ -const xdr = SorobanClient.xdr; - describe("assembleTransaction", () => { describe("FeeBumpTransaction", () => { // TODO: Add support for fee bump transactions }); + const fnAuth = new SorobanClient.xdr.ContractAuth({ + addressWithNonce: new SorobanClient.xdr.AddressWithNonce({ + address: SorobanClient.xdr.ScAddress.scAddressTypeAccount( + SorobanClient.xdr.PublicKey.publicKeyTypeEd25519( + SorobanClient.StrKey.decodeEd25519PublicKey( + "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI", + ), + ), + ), + nonce: SorobanClient.xdr.Uint64.fromString("0"), + }), + rootInvocation: new SorobanClient.xdr.AuthorizedInvocation({ + contractId: Buffer.alloc(32), + functionName: Buffer.from("fn"), + args: [], + subInvocations: [], + }), + signatureArgs: [], + }); + + const sorobanTransactionData = new SorobanClient.xdr.SorobanTransactionData({ + resources: new SorobanClient.xdr.SorobanResources({ + footprint: new SorobanClient.xdr.LedgerFootprint({ + readOnly: [], + readWrite: [], + }), + instructions: 0, + readBytes: 5, + writeBytes: 0, + extendedMetaDataSizeBytes: 0, + }), + refundableFee: SorobanClient.xdr.Int64.fromString("0"), + ext: new SorobanClient.xdr.ExtensionPoint(0), + }); + + const simulationResponse = { + transactionData: sorobanTransactionData.toXDR("base64"), + events: [], + minResourceFee: "115", + results: [ + { + auth: [fnAuth.toXDR("base64")], + xdr: SorobanClient.xdr.ScVal.scvU32(0) + .toXDR() + .toString("base64"), + }, + ], + latestLedger: 3, + cost: { + cpuInsns: "0", + memBytes: "0", + }, + }; describe("Transaction", () => { const networkPassphrase = SorobanClient.Networks.TESTNET; const source = new SorobanClient.Account( "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI", "1" ); - const emptyFootprint = new xdr.LedgerFootprint({ - readOnly: [], - readWrite: [], - }); - function emptyTransaction() { + + function singleContractFnTransaction() { return new SorobanClient.TransactionBuilder(source, { fee: 100, - networkPassphrase, + networkPassphrase: "Test", v1: true, }) .addOperation( SorobanClient.Operation.invokeHostFunction({ - function: xdr.HostFunction.hostFunctionTypeInvokeContract([]), - parameters: [], - footprint: emptyFootprint, + args: new SorobanClient.xdr.HostFunctionArgs.hostFunctionTypeInvokeContract( + [], + ), auth: [], }) ) @@ -33,50 +81,75 @@ describe("assembleTransaction", () => { .build(); } - it("adds the footprint to the transaction", () => { - const txn = emptyTransaction(); - - const result = SorobanClient.assembleTransaction(txn, networkPassphrase, [ - { - auth: [], - footprint: new xdr.LedgerFootprint({ - readOnly: [ - xdr.LedgerKey.contractCode( - new xdr.LedgerKeyContractCode({ - hash: Buffer.alloc(32), - }) - ), - ], - readWrite: [], - }), - }, - ]); + it("simulate updates the tx data from simulation response", () => { + const txn = singleContractFnTransaction(); + const result = SorobanClient.assembleTransaction( + txn, + networkPassphrase, + simulationResponse, + ); - expect(result.operations[0].footprint.readOnly.length).to.equal(1); + // validate it auto updated the tx fees from sim response fees + // since it was greater than tx.fee + expect( + result + .toEnvelope() + .v1() + .tx() + .fee(), + ).to.equal(215); + + // validate it udpated sorobantransactiondata block in the tx ext + expect( + result + .toEnvelope() + .v1() + .tx() + .ext() + .sorobanData(), + ).to.deep.equal(sorobanTransactionData); }); - it("adds the auth to the transaction", () => { - const txn = emptyTransaction(); - - const result = SorobanClient.assembleTransaction(txn, networkPassphrase, [ - { - auth: [ - new xdr.ContractAuth({ - addressWithNonce: null, - rootInvocation: new xdr.AuthorizedInvocation({ - contractId: Buffer.alloc(32), - functionName: "foo", - args: [], - subInvocations: [], - }), - signatureArgs: [], - }), - ], - footprint: emptyFootprint, - }, - ]); - - expect(result.operations[0].auth.length).to.equal(1); + it("simulate adds the auth to the host function in tx operation", () => { + const txn = singleContractFnTransaction(); + const result = SorobanClient.assembleTransaction( + txn, + networkPassphrase, + simulationResponse, + ); + + expect( + result + .toEnvelope() + .v1() + .tx() + .operations()[0] + .body() + .invokeHostFunctionOp() + .functions()[0] + .auth()[0] + .rootInvocation() + .functionName() + .toString(), + ).to.equal("fn"); + + expect( + SorobanClient.StrKey.encodeEd25519PublicKey( + result + .toEnvelope() + .v1() + .tx() + .operations()[0] + .body() + .invokeHostFunctionOp() + .functions()[0] + .auth()[0] + .addressWithNonce() + .address() + .accountId() + .ed25519(), + ), + ).to.equal("GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"); }); it("throws for non-invokehost-fn ops", () => { @@ -94,21 +167,107 @@ describe("assembleTransaction", () => { .build(); try { - SorobanClient.assembleTransaction(txn, networkPassphrase, [null]); + SorobanClient.assembleTransaction(txn, networkPassphrase, { + transactionData: {}, + events: [], + minResourceFee: "0", + results: [], + latestLedger: 3, + }); + expect.fail(); + } catch (err) { + expect(err.toString()).to.equal( + "Error: unsupported operation type, must be only one InvokeHostFunctionOp in the transaction.", + ); + } + }); + + it("throws for mismatched HostFunctions between simulation and tx", () => { + const txn = new SorobanClient.TransactionBuilder(source, { + fee: 100, + networkPassphrase: "Test", + v1: true, + }) + .addOperation( + SorobanClient.Operation.invokeHostFunctions({ + functions: [ + new SorobanClient.xdr.HostFunction({ + args: new SorobanClient.xdr.HostFunctionArgs.hostFunctionTypeInvokeContract( + [], + ), + auth: [], + }), + new SorobanClient.xdr.HostFunction({ + args: new SorobanClient.xdr.HostFunctionArgs.hostFunctionTypeInvokeContract( + [], + ), + auth: [], + }), + ], + }), + ) + .setTimeout(SorobanClient.TimeoutInfinite) + .build(); + + try { + SorobanClient.assembleTransaction( + txn, + networkPassphrase, + simulationResponse, + ); expect.fail(); } catch (err) { - expect(err.toString()).to.equal("Error: Unsupported operation type"); + expect(err.toString()).to.equal( + "Error: preflight simulation results do not contain same count of HostFunctions that InvokeHostFunctionOp in the transaction has.", + ); } }); - it("handles transactions with no auth or footprint", () => { - const txn = emptyTransaction(); + it("handles no host functions", () => { + const txn = new SorobanClient.TransactionBuilder(source, { + fee: 100, + networkPassphrase: "Test", + v1: true, + }) + .addOperation( + SorobanClient.Operation.invokeHostFunctions({ + functions: [], + }), + ) + .setTimeout(SorobanClient.TimeoutInfinite) + .build(); + + const noSorobanData = new SorobanClient.xdr.SorobanTransactionData({ + resources: new SorobanClient.xdr.SorobanResources({ + footprint: new SorobanClient.xdr.LedgerFootprint({ + readOnly: [], + readWrite: [], + }), + instructions: 0, + readBytes: 0, + writeBytes: 0, + extendedMetaDataSizeBytes: 0, + }), + refundableFee: SorobanClient.xdr.Int64.fromString("0"), + ext: new SorobanClient.xdr.ExtensionPoint(0), + }).toXDR("base64"); - const result = SorobanClient.assembleTransaction(txn, networkPassphrase, [ - {}, - ]); + const result = SorobanClient.assembleTransaction(txn, networkPassphrase, { + results: [], + events: [], + transactionData: noSorobanData, + }); - expect(result.operations[0].auth.length).to.equal(0); + expect( + result + .toEnvelope() + .v1() + .tx() + .operations()[0] + .body() + .invokeHostFunctionOp() + .functions(), + ).to.have.length(0); }); }); }); diff --git a/yarn.lock b/yarn.lock index 6d7e6b41..f7cb1636 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1296,9 +1296,9 @@ type-detect "4.0.8" "@sinonjs/fake-timers@^10.0.2": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.1.0.tgz#3595e42b3f0a7df80a9681cf58d8cb418eac1e99" - integrity sha512-w1qd368vtrwttm1PRJWPW1QHlbmHrVDGs1eBH/jZvRPUFS4MNXV9Q33EQdjOdeAxZ7O8+3wM7zxztm2nfUSyKw== + version "10.2.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz#b3e322a34c5f26e3184e7f6115695f299c1b1194" + integrity sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg== dependencies: "@sinonjs/commons" "^3.0.0" @@ -1452,9 +1452,9 @@ integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== "@types/node@*", "@types/node@>=10.0.0", "@types/node@^20.1.7": - version "20.1.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.1.7.tgz#ce10c802f7731909d0a44ac9888e8b3a9125eb62" - integrity sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg== + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.1.tgz#de559d4b33be9a808fd43372ccee822c70f39704" + integrity sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg== "@types/node@^14.14.35": version "14.18.47" @@ -2030,7 +2030,7 @@ axios-mock-adapter@^1.21.4: fast-deep-equal "^3.1.3" is-buffer "^2.0.5" -axios@1.4.0: +axios@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== @@ -2118,11 +2118,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bignumber.js@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== - bignumber.js@^9.1.1: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" @@ -2288,7 +2283,7 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@^5.1.0, buffer@^5.5.0: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2723,12 +2718,10 @@ cors@~2.8.5: object-assign "^4" vary "^1" -crc@^3.5.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" - integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== - dependencies: - buffer "^5.1.0" +crc@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/crc/-/crc-4.3.2.tgz#49b7821cbf2cf61dfd079ed93863bbebd5469b9a" + integrity sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A== create-ecdh@^4.0.0: version "4.0.4" @@ -2996,9 +2989,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.4.284: - version "1.4.398" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.398.tgz#b0fd3092b07d81c2ebf63f8395aa8a70c2c0892d" - integrity sha512-tT90Lmieb+Y4jX5Awub8BsvuFM/ICKr01oZFBR9Cy6pxCf+rAmwcpRl4xfXb66DzTXc4qSMPqlqLDoghm27utQ== + version "1.4.399" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.399.tgz#df8a63d1f572124ad8b5d846e38b0532ad7d9d54" + integrity sha512-+V1aNvVgoWNWYIbMOiQ1n5fRIaY4SlQ/uRlrsCjLrUwr/3OvQgiX2f5vdav4oArVT9TnttJKcPCqjwPNyZqw/A== elliptic@^6.5.3: version "6.5.4" @@ -4545,13 +4538,10 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-xdr@^1.1.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/js-xdr/-/js-xdr-1.3.0.tgz#e72e77c00bbdae62689062b95fe35ae2bd90df32" - integrity sha512-fjLTm2uBtFvWsE3l2J14VjTuuB8vJfeTtYuNS7LiLHDWIX2kt0l1pqq9334F8kODUkKPMuULjEcbGbkFFwhx5g== - dependencies: - lodash "^4.17.5" - long "^2.2.3" +js-xdr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/js-xdr/-/js-xdr-2.0.0.tgz#ef24ea27369ab60217c001fd0e27301f6981ba0a" + integrity sha512-4mctWHR47ejNcfpE8/Xl3l2wYqO1Qy09d1pveZRmarUz2BcuU/M8grzadxV6PoN/X0ywOb6cy6117qYUWkfeBA== js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" @@ -4899,7 +4889,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.5: +lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4933,11 +4923,6 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.5" -long@^2.2.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f" - integrity sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ== - loupe@^2.3.1: version "2.3.6" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" @@ -6278,10 +6263,10 @@ socket.io@^4.4.1: socket.io-adapter "~2.5.2" socket.io-parser "~4.2.1" -sodium-native@^3.3.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-3.4.1.tgz#44616c07ccecea15195f553af88b3e574b659741" - integrity sha512-PaNN/roiFWzVVTL6OqjzYct38NSXewdl2wz8SRB51Br/MLIJPrbM3XexhVWkq7D3UWMysfrhKVf1v1phZq6MeQ== +sodium-native@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-4.0.1.tgz#773201b0d7872da294b9b12cd90d4a913dc9a2dd" + integrity sha512-OQTaxrVLtMvrnfcwZVsOTHe58MfDApJiHJNoOwcmmrhwvlYkfaUt2WuzRio8PgEMOd96R5aDHY49DCtock1zsA== dependencies: node-gyp-build "^4.3.0" @@ -6383,20 +6368,21 @@ statuses@~1.5.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -stellar-base@v8.2.2-soroban.12: - version "8.2.2-soroban.12" - resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-8.2.2-soroban.12.tgz#81392ae6ea5c8b2316faacd2304a13c23ec850db" - integrity sha512-bQQxRFA2GXoNsr2ZFN+eK9Du1hSu0+t983tHRMI3nyWlLgZInKg7B9ZFa4UjLbLYpxQ4mE1EYupk3bulqNA91A== +stellar-base@^9.0.0-soroban.1: + version "9.0.0-soroban.1" + resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-9.0.0-soroban.1.tgz#92a1879329f79190d3f242ac8163be712be90704" + integrity sha512-oLqE3kNFMo6Hhd9VgBN8jMfaw9RypVqYmdCDDn3NufxIZW92bP7Jq0oPf28N/YO7DYOT7oqptqf7+DVDcwvfZg== dependencies: base32.js "^0.1.0" - bignumber.js "^4.0.0" - crc "^3.5.0" - js-xdr "^1.1.3" + bignumber.js "^9.1.1" + crc "^4.3.2" + crypto-browserify "^3.12.0" + js-xdr "^2.0.0" lodash "^4.17.21" sha.js "^2.3.6" tweetnacl "^1.0.3" optionalDependencies: - sodium-native "^3.3.0" + sodium-native "^4.0.1" stream-browserify@^3.0.0: version "3.0.0" @@ -6625,9 +6611,9 @@ tar@^6.1.11: yallist "^4.0.0" terser-webpack-plugin@^5.3.7, terser-webpack-plugin@^5.3.8: - version "5.3.8" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.8.tgz#415e03d2508f7de63d59eca85c5d102838f06610" - integrity sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg== + version "5.3.9" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== dependencies: "@jridgewell/trace-mapping" "^0.3.17" jest-worker "^27.4.5" @@ -6743,9 +6729,9 @@ tslib@^1.8.0, tslib@^1.8.1: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + version "2.5.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.1.tgz#f2ad78c367857d54e49a0ef9def68737e1a67b21" + integrity sha512-KaI6gPil5m9vF7DKaoXxx1ia9fxS4qG5YveErRRVknPDXXriu5M8h48YRjB6h5ZUOKuAKlSJYb0GaDe8I39fRw== tslint@5.14.0: version "5.14.0"