diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 384f85d2d..5fddac7a3 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest-4-cores env: # the gh tag of system-test repo version to run - SYSTEM_TEST_GIT_REF: 4e459608f22b51ba5ee3c061d6d1a8641f16f7e0 + SYSTEM_TEST_GIT_REF: 352cc1d4ea96af8cfb2c2b7335c3b51da000f889 # the soroban tools source code to compile and run from system test # refers to checked out source of current git hub ref context @@ -22,10 +22,11 @@ jobs: # core git ref should be latest commit for stable soroban functionality # the core bin can either be compiled in-line here as part of ci, - SYSTEM_TEST_CORE_GIT_REF: https://github.com/stellar/stellar-core.git#2b283bd9ef3958a3ef477af36a3ff113a86d535b - SYSTEM_TEST_CORE_COMPILE_CONFIGURE_FLAGS: "--disable-tests --enable-next-protocol-version-unsafe-for-production" - # or can use option to pull a pre-compiled image instead - # SYSTEM_TEST_CORE_IMAGE: + SYSTEM_TEST_CORE_GIT_REF: https://github.com/stellar/stellar-core.git#ecb24df104c2453a00fa5097d2e879d7731b9596 + SYSTEM_TEST_CORE_COMPILE_CONFIGURE_FLAGS: "--disable-tests" + # or set SYSTEM_TEST_CORE_GIT_REF to empty, and set SYSTEM_TEST_CORE_IMAGE + # to pull a pre-compiled image from dockerhub instead + SYSTEM_TEST_CORE_IMAGE: # sets the version of rust toolchain that will be pre-installed in the # test runtime environment, tests invoke rustc/cargo @@ -35,15 +36,16 @@ jobs: # resolution options, using npm release or a gh ref: # # option #1, set the version of soroban-js-client based on a npm release version - SYSTEM_TEST_JS_SOROBAN_CLIENT_NPM_VERSION: + SYSTEM_TEST_JS_SOROBAN_CLIENT_NPM_VERSION: 1.0.0-beta.2 # option #2, set the version of soroban-js-client used as a ref to a gh repo - # if this value is present it takes precedence over any SYSTEM_TEST_JS_SOROBAN_CLIENT_NPM_VERSION - SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO: stellar/js-soroban-client - SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REF: refs/pull/135/head + # if a value is set on SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO, it takes precedence + # over any SYSTEM_TEST_JS_SOROBAN_CLIENT_NPM_VERSION + SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO: + SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REF: # system test will build quickstart image internally to use for running the service stack # configured in standalone network mode(core, rpc) - SYSTEM_TEST_QUICKSTART_GIT_REF: https://github.com/stellar/quickstart.git#c8826f5d8f80d54e819d1aca310cec3005f89175 + SYSTEM_TEST_QUICKSTART_GIT_REF: https://github.com/stellar/quickstart.git#69a1089eee9aaac4bafe4cbfc0639de18222db6a # triggers system test to log out details from quickstart's logs and test steps SYSTEM_TEST_VERBOSE_OUTPUT: "true" @@ -62,11 +64,11 @@ jobs: name: checkout soroban-tools with: path: soroban-tools - - if: ${{ env.SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO }} + - if: ${{ env.SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO != ''}} name: prepare local js-soroban-client run: | rm -rf $GITHUB_WORKSPACE/system-test/js-soroban-client; - - if: ${{ env.SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO }} + - if: ${{ env.SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO != ''}} uses: actions/checkout@v3 with: repository: ${{ env.SYSTEM_TEST_JS_SOROBAN_CLIENT_GH_REPO }} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md index 03f87f30b..86ef3b7e4 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md @@ -6,7 +6,7 @@ This library was automatically generated by Soroban CLI using a command similar ```bash soroban contract bindings ts \ - --rpc-url https://rpc-futurenet.stellar.org:443 \ + --rpc-url https://rpc-futurenet.stellar.org:443/soroban/rpc \ --network-passphrase "Test SDF Future Network ; October 2022" \ --contract-id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK \ --output-dir ./path/to/test_custom_types @@ -30,7 +30,7 @@ However, we've actually encountered [frustration](https://github.com/stellar/sor ```json "scripts": { - "postinstall": "soroban contract bindings ts --rpc-url https://rpc-futurenet.stellar.org:443 --network-passphrase \"Test SDF Future Network ; October 2022\" --id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK --name test_custom_types" + "postinstall": "soroban contract bindings ts --rpc-url https://rpc-futurenet.stellar.org:443/soroban/rpc --network-passphrase \"Test SDF Future Network ; October 2022\" --id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK --name test_custom_types" } ``` diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/convert.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/convert.js index 10fafc124..ea86fbaf4 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/convert.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/convert.js @@ -2,9 +2,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.u128ToScVal = exports.i128ToScVal = exports.addressToScVal = exports.scValToJs = exports.scValStrToJs = exports.strToScVal = void 0; const soroban_client_1 = require("soroban-client"); -const buffer_1 = require("buffer"); function strToScVal(base64Xdr) { - return soroban_client_1.xdr.ScVal.fromXDR(buffer_1.Buffer.from(base64Xdr, 'base64')); + return soroban_client_1.xdr.ScVal.fromXDR(base64Xdr, 'base64'); } exports.strToScVal = strToScVal; function scValStrToJs(base64Xdr) { @@ -32,7 +31,7 @@ function scValToJs(val) { case soroban_client_1.xdr.ScValType.scvI128(): case soroban_client_1.xdr.ScValType.scvU256(): case soroban_client_1.xdr.ScValType.scvI256(): { - return (0, soroban_client_1.scValToBigInt)(val); + return soroban_client_1.scValToBigInt(val); } case soroban_client_1.xdr.ScValType.scvAddress(): { return soroban_client_1.Address.fromScVal(val).toString(); @@ -77,13 +76,10 @@ function scValToJs(val) { return res; } case soroban_client_1.xdr.ScValType.scvContractInstance(): - return val.instance(); case soroban_client_1.xdr.ScValType.scvLedgerKeyNonce(): - return val.nonceKey(); case soroban_client_1.xdr.ScValType.scvTimepoint(): - return val.timepoint(); case soroban_client_1.xdr.ScValType.scvDuration(): - return val.duration(); + return val.value(); // TODO: Add this case when merged // case xdr.ScValType.scvError(): default: { @@ -94,8 +90,7 @@ function scValToJs(val) { } exports.scValToJs = scValToJs; function addressToScVal(addr) { - let addrObj = soroban_client_1.Address.fromString(addr); - return addrObj.toScVal(); + return soroban_client_1.nativeToScVal(addr, { type: 'address' } /* bug workaround */); } exports.addressToScVal = addressToScVal; function i128ToScVal(i) { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.d.ts index 96512dce6..afc811097 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.d.ts @@ -4,17 +4,17 @@ import { Buffer } from "buffer"; import type { ResponseTypes, ClassOptions } from './method-options.js'; export * from './invoke.js'; export * from './method-options.js'; -export type u32 = number; -export type i32 = number; -export type u64 = bigint; -export type i64 = bigint; -export type u128 = bigint; -export type i128 = bigint; -export type u256 = bigint; -export type i256 = bigint; -export type Option = T | undefined; -export type Typepoint = bigint; -export type Duration = bigint; +export declare type u32 = number; +export declare type i32 = number; +export declare type u64 = bigint; +export declare type i64 = bigint; +export declare type u128 = bigint; +export declare type i128 = bigint; +export declare type u256 = bigint; +export declare type i256 = bigint; +export declare type Option = T | undefined; +export declare type Typepoint = bigint; +export declare type Duration = bigint; export { Address }; export interface Error_ { message: string; @@ -55,7 +55,7 @@ export interface Test { b: boolean; c: string; } -export type SimpleEnum = { +export declare type SimpleEnum = { tag: "First"; values: void; } | { @@ -70,8 +70,8 @@ export declare enum RoyalCard { Queen = 12, King = 13 } -export type TupleStruct = readonly [Test, SimpleEnum]; -export type ComplexEnum = { +export declare type TupleStruct = readonly [Test, SimpleEnum]; +export declare type ComplexEnum = { tag: "Struct"; values: readonly [Test]; } | { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.js index bd2b1e4ef..a03274e97 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/index.js @@ -1,11 +1,7 @@ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -24,7 +20,6 @@ __exportStar(require("./method-options.js"), exports); ; ; class Ok { - value; constructor(value) { this.value = value; } @@ -43,7 +38,6 @@ class Ok { } exports.Ok = Ok; class Err { - error; constructor(error) { this.error = error; } @@ -92,13 +86,11 @@ var RoyalCard; RoyalCard[RoyalCard["Jack"] = 11] = "Jack"; RoyalCard[RoyalCard["Queen"] = 12] = "Queen"; RoyalCard[RoyalCard["King"] = 13] = "King"; -})(RoyalCard || (exports.RoyalCard = RoyalCard = {})); +})(RoyalCard = exports.RoyalCard || (exports.RoyalCard = {})); const Errors = { 1: { message: "Please provide an odd number" } }; class Contract { - options; - spec; constructor(options) { this.options = options; this.spec = new soroban_client_1.ContractSpec([ @@ -139,7 +131,7 @@ class Contract { ]); } async hello({ hello }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'hello', args: this.spec.funcArgsToScVals("hello", { hello }), ...options, @@ -150,7 +142,7 @@ class Contract { }); } async woid(options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'woid', args: this.spec.funcArgsToScVals("woid", {}), ...options, @@ -159,7 +151,7 @@ class Contract { }); } async val(options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'val', args: this.spec.funcArgsToScVals("val", {}), ...options, @@ -171,7 +163,7 @@ class Contract { } async u32FailOnEven({ u32_ }, options = {}) { try { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'u32_fail_on_even', args: this.spec.funcArgsToScVals("u32_fail_on_even", { u32_ }), ...options, @@ -182,7 +174,6 @@ class Contract { }); } catch (e) { - console.log(e); if (typeof e === 'string') { let err = parseError(e); if (err) @@ -192,7 +183,7 @@ class Contract { } } async u32({ u32_ }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'u32_', args: this.spec.funcArgsToScVals("u32_", { u32_ }), ...options, @@ -203,7 +194,7 @@ class Contract { }); } async i32({ i32_ }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'i32_', args: this.spec.funcArgsToScVals("i32_", { i32_ }), ...options, @@ -214,7 +205,7 @@ class Contract { }); } async i64({ i64_ }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'i64_', args: this.spec.funcArgsToScVals("i64_", { i64_ }), ...options, @@ -228,7 +219,7 @@ class Contract { * Example contract method which takes a struct */ async struktHel({ strukt }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'strukt_hel', args: this.spec.funcArgsToScVals("strukt_hel", { strukt }), ...options, @@ -239,7 +230,7 @@ class Contract { }); } async strukt({ strukt }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'strukt', args: this.spec.funcArgsToScVals("strukt", { strukt }), ...options, @@ -250,7 +241,7 @@ class Contract { }); } async simple({ simple }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'simple', args: this.spec.funcArgsToScVals("simple", { simple }), ...options, @@ -261,7 +252,7 @@ class Contract { }); } async complex({ complex }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'complex', args: this.spec.funcArgsToScVals("complex", { complex }), ...options, @@ -272,7 +263,7 @@ class Contract { }); } async addresse({ addresse }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'addresse', args: this.spec.funcArgsToScVals("addresse", { addresse }), ...options, @@ -283,7 +274,7 @@ class Contract { }); } async bytes({ bytes }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'bytes', args: this.spec.funcArgsToScVals("bytes", { bytes }), ...options, @@ -294,7 +285,7 @@ class Contract { }); } async bytesN({ bytes_n }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'bytes_n', args: this.spec.funcArgsToScVals("bytes_n", { bytes_n }), ...options, @@ -305,7 +296,7 @@ class Contract { }); } async card({ card }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'card', args: this.spec.funcArgsToScVals("card", { card }), ...options, @@ -316,7 +307,7 @@ class Contract { }); } async boolean({ boolean }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'boolean', args: this.spec.funcArgsToScVals("boolean", { boolean }), ...options, @@ -330,7 +321,7 @@ class Contract { * Negates a boolean value */ async not({ boolean }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'not', args: this.spec.funcArgsToScVals("not", { boolean }), ...options, @@ -341,7 +332,7 @@ class Contract { }); } async i128({ i128 }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'i128', args: this.spec.funcArgsToScVals("i128", { i128 }), ...options, @@ -352,7 +343,7 @@ class Contract { }); } async u128({ u128 }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'u128', args: this.spec.funcArgsToScVals("u128", { u128 }), ...options, @@ -363,7 +354,7 @@ class Contract { }); } async multiArgs({ a, b }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'multi_args', args: this.spec.funcArgsToScVals("multi_args", { a, b }), ...options, @@ -374,7 +365,7 @@ class Contract { }); } async map({ map }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'map', args: this.spec.funcArgsToScVals("map", { map }), ...options, @@ -385,7 +376,7 @@ class Contract { }); } async vec({ vec }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'vec', args: this.spec.funcArgsToScVals("vec", { vec }), ...options, @@ -396,7 +387,7 @@ class Contract { }); } async tuple({ tuple }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'tuple', args: this.spec.funcArgsToScVals("tuple", { tuple }), ...options, @@ -410,7 +401,7 @@ class Contract { * Example of an optional argument */ async option({ option }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'option', args: this.spec.funcArgsToScVals("option", { option }), ...options, @@ -421,7 +412,7 @@ class Contract { }); } async u256({ u256 }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'u256', args: this.spec.funcArgsToScVals("u256", { u256 }), ...options, @@ -432,7 +423,7 @@ class Contract { }); } async i256({ i256 }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'i256', args: this.spec.funcArgsToScVals("i256", { i256 }), ...options, @@ -443,7 +434,7 @@ class Contract { }); } async string({ string }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'string', args: this.spec.funcArgsToScVals("string", { string }), ...options, @@ -454,7 +445,7 @@ class Contract { }); } async tupleStrukt({ tuple_strukt }, options = {}) { - return await (0, invoke_js_1.invoke)({ + return await invoke_js_1.invoke({ method: 'tuple_strukt', args: this.spec.funcArgsToScVals("tuple_strukt", { tuple_strukt }), ...options, diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.d.ts index 4e8e95394..1934a69a6 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.d.ts @@ -1,15 +1,16 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; import type { Memo, MemoType, Operation, Transaction, xdr } from "soroban-client"; import type { ClassOptions, MethodOptions, ResponseTypes, Wallet } from "./method-options.js"; -export type Tx = Transaction, Operation[]>; +export declare type Tx = Transaction, Operation[]>; export declare class NotImplementedError extends Error { } -type Simulation = SorobanClient.SorobanRpc.SimulateTransactionResponse; -type SendTx = SorobanClient.SorobanRpc.SendTransactionResponse; -type GetTx = SorobanClient.SorobanRpc.GetTransactionResponse; +declare type Simulation = SorobanRpc.SimulateTransactionResponse; +declare type SendTx = SorobanRpc.SendTransactionResponse; +declare type GetTx = SorobanRpc.GetTransactionResponse; declare let someRpcResponse: Simulation | SendTx | GetTx; -type SomeRpcResponse = typeof someRpcResponse; -type InvokeArgs = MethodOptions & ClassOptions & { +declare type SomeRpcResponse = typeof someRpcResponse; +declare type InvokeArgs = MethodOptions & ClassOptions & { method: string; args?: any[]; parseResultXdr: (xdr: string | xdr.ScVal) => T; diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.js index f7de5eede..c6e606fe5 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/invoke.js @@ -2,6 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.sendTx = exports.signTx = exports.invoke = exports.NotImplementedError = void 0; const SorobanClient = require("soroban-client"); +const soroban_client_1 = require("soroban-client"); /** * Get account details from the Soroban network for the publicKey currently * selected in Freighter. If not connected to Freighter, return null. @@ -36,35 +37,28 @@ async function invoke({ method, args = [], fee = 100, responseType, parseResultX fee: fee.toString(10), networkPassphrase, }) + .setNetworkPassphrase(networkPassphrase) .addOperation(contract.call(method, ...args)) .setTimeout(SorobanClient.TimeoutInfinite) .build(); - console.log(method, args); const simulated = await server.simulateTransaction(tx); - console.log("---\n", simulated.result.retval, "\n----"); - if (simulated.error) - throw simulated.error; - if (responseType === "simulated") + if (soroban_client_1.SorobanRpc.isSimulationError(simulated)) { + throw new Error(simulated.error); + } + else if (responseType === "simulated") { return simulated; - // is it possible for `auths` to be present but empty? Probably not, but let's be safe. - let authsCount = simulated.result.auth?.length ?? 0; - const writeLength = simulated.transactionData - .build() - .resources() - .footprint() - .readWrite().length; - const isViewCall = authsCount === 0 && writeLength === 0; + } + else if (!simulated.result) { + throw new Error(`invalid simulation: no result in ${simulated}`); + } + let authsCount = simulated.result.auth.length; + const writeLength = simulated.transactionData.getReadWrite().length; + const isViewCall = (authsCount === 0) && (writeLength === 0); if (isViewCall) { - if (responseType === "full") + if (responseType === "full") { return simulated; - const retval = simulated.result?.retval; - if (!retval) { - if (simulated.error) { - throw new Error(simulated.error); - } - throw new Error(`Invalid response from simulateTransaction:\n{simulated}`); } - return parseResultXdr(retval); + return parseResultXdr(simulated.result.retval); } if (authsCount > 1) { throw new NotImplementedError("Multiple auths not yet supported"); @@ -84,15 +78,24 @@ async function invoke({ method, args = [], fee = 100, responseType, parseResultX } tx = await signTx(wallet, SorobanClient.assembleTransaction(tx, networkPassphrase, simulated).build(), networkPassphrase); const raw = await sendTx(tx, secondsToWait, server); - if (responseType === "full") + if (responseType === "full") { return raw; + } // if `sendTx` awaited the inclusion of the tx in the ledger, it used // `getTransaction`, which has a `resultXdr` field - if ("resultXdr" in raw) + if ("resultXdr" in raw) { + const getResult = raw; + if (getResult.status !== soroban_client_1.SorobanRpc.GetTransactionStatus.SUCCESS) { + console.error('Transaction submission failed! Returning full RPC response.'); + return raw; + } return parse(raw.resultXdr.result().toXDR("base64")); + } // otherwise, it returned the result of `sendTransaction` - if ("errorResultXdr" in raw) - return parse(raw.errorResultXdr); + if ("errorResultXdr" in raw) { + const sendResult = raw; + return parse(sendResult.errorResultXdr); + } // if neither of these are present, something went wrong console.error("Don't know how to parse result! Returning full RPC response."); return raw; @@ -133,7 +136,7 @@ async function sendTx(tx, secondsToWait, server) { let waitTime = 1000; let exponentialFactor = 1.5; while (Date.now() < waitUntil && - getTransactionResponse.status === "NOT_FOUND") { + getTransactionResponse.status === soroban_client_1.SorobanRpc.GetTransactionStatus.NOT_FOUND) { // Wait a beat await new Promise((resolve) => setTimeout(resolve, waitTime)); /// Exponential backoff @@ -141,8 +144,10 @@ async function sendTx(tx, secondsToWait, server) { // See if the transaction is complete getTransactionResponse = await server.getTransaction(sendTransactionResponse.hash); } - if (getTransactionResponse.status === "NOT_FOUND") { - console.error(`Waited ${secondsToWait} seconds for transaction to complete, but it did not. Returning anyway. Check the transaction status manually. Info: ${JSON.stringify(sendTransactionResponse, null, 2)}`); + if (getTransactionResponse.status === soroban_client_1.SorobanRpc.GetTransactionStatus.NOT_FOUND) { + console.error(`Waited ${secondsToWait} seconds for transaction to complete, but it did not. ` + + `Returning anyway. Check the transaction status manually. ` + + `Info: ${JSON.stringify(sendTransactionResponse, null, 2)}`); } return getTransactionResponse; } diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/method-options.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/method-options.d.ts index f861ff1f2..a959d97f2 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/method-options.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/cjs/method-options.d.ts @@ -1,6 +1,6 @@ declare let responseTypes: 'simulated' | 'full' | undefined; -export type ResponseTypes = typeof responseTypes; -export type XDR_BASE64 = string; +export declare type ResponseTypes = typeof responseTypes; +export declare type XDR_BASE64 = string; export interface Wallet { isConnected: () => Promise; isAllowed: () => Promise; @@ -13,7 +13,7 @@ export interface Wallet { accountToSign?: string; }) => Promise; } -export type ClassOptions = { +export declare type ClassOptions = { contractId: string; networkPassphrase: string; rpcUrl: string; @@ -32,7 +32,7 @@ export type ClassOptions = { */ wallet?: Wallet; }; -export type MethodOptions = { +export declare type MethodOptions = { /** * The fee to pay for the transaction. Default: 100. */ diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/convert.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/convert.js index 72a8d1cbc..4faf03e15 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/convert.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/convert.js @@ -1,7 +1,6 @@ -import { Address, xdr, scValToBigInt, ScInt } from 'soroban-client'; -import { Buffer } from "buffer"; +import { xdr, Address, nativeToScVal, scValToBigInt, ScInt } from 'soroban-client'; export function strToScVal(base64Xdr) { - return xdr.ScVal.fromXDR(Buffer.from(base64Xdr, 'base64')); + return xdr.ScVal.fromXDR(base64Xdr, 'base64'); } export function scValStrToJs(base64Xdr) { return scValToJs(strToScVal(base64Xdr)); @@ -72,13 +71,10 @@ export function scValToJs(val) { return res; } case xdr.ScValType.scvContractInstance(): - return val.instance(); case xdr.ScValType.scvLedgerKeyNonce(): - return val.nonceKey(); case xdr.ScValType.scvTimepoint(): - return val.timepoint(); case xdr.ScValType.scvDuration(): - return val.duration(); + return val.value(); // TODO: Add this case when merged // case xdr.ScValType.scvError(): default: { @@ -88,8 +84,7 @@ export function scValToJs(val) { ; } export function addressToScVal(addr) { - let addrObj = Address.fromString(addr); - return addrObj.toScVal(); + return nativeToScVal(addr, { type: 'address' } /* bug workaround */); } export function i128ToScVal(i) { return new ScInt(i).toI128(); diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.d.ts index 96512dce6..afc811097 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.d.ts @@ -4,17 +4,17 @@ import { Buffer } from "buffer"; import type { ResponseTypes, ClassOptions } from './method-options.js'; export * from './invoke.js'; export * from './method-options.js'; -export type u32 = number; -export type i32 = number; -export type u64 = bigint; -export type i64 = bigint; -export type u128 = bigint; -export type i128 = bigint; -export type u256 = bigint; -export type i256 = bigint; -export type Option = T | undefined; -export type Typepoint = bigint; -export type Duration = bigint; +export declare type u32 = number; +export declare type i32 = number; +export declare type u64 = bigint; +export declare type i64 = bigint; +export declare type u128 = bigint; +export declare type i128 = bigint; +export declare type u256 = bigint; +export declare type i256 = bigint; +export declare type Option = T | undefined; +export declare type Typepoint = bigint; +export declare type Duration = bigint; export { Address }; export interface Error_ { message: string; @@ -55,7 +55,7 @@ export interface Test { b: boolean; c: string; } -export type SimpleEnum = { +export declare type SimpleEnum = { tag: "First"; values: void; } | { @@ -70,8 +70,8 @@ export declare enum RoyalCard { Queen = 12, King = 13 } -export type TupleStruct = readonly [Test, SimpleEnum]; -export type ComplexEnum = { +export declare type TupleStruct = readonly [Test, SimpleEnum]; +export declare type ComplexEnum = { tag: "Struct"; values: readonly [Test]; } | { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.js index 9552e6182..9b6aab750 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/index.js @@ -7,7 +7,6 @@ export { Address }; ; ; export class Ok { - value; constructor(value) { this.value = value; } @@ -25,7 +24,6 @@ export class Ok { } } export class Err { - error; constructor(error) { this.error = error; } @@ -78,8 +76,6 @@ const Errors = { 1: { message: "Please provide an odd number" } }; export class Contract { - options; - spec; constructor(options) { this.options = options; this.spec = new ContractSpec([ @@ -163,7 +159,6 @@ export class Contract { }); } catch (e) { - console.log(e); if (typeof e === 'string') { let err = parseError(e); if (err) diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.d.ts index 4e8e95394..1934a69a6 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.d.ts @@ -1,15 +1,16 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; import type { Memo, MemoType, Operation, Transaction, xdr } from "soroban-client"; import type { ClassOptions, MethodOptions, ResponseTypes, Wallet } from "./method-options.js"; -export type Tx = Transaction, Operation[]>; +export declare type Tx = Transaction, Operation[]>; export declare class NotImplementedError extends Error { } -type Simulation = SorobanClient.SorobanRpc.SimulateTransactionResponse; -type SendTx = SorobanClient.SorobanRpc.SendTransactionResponse; -type GetTx = SorobanClient.SorobanRpc.GetTransactionResponse; +declare type Simulation = SorobanRpc.SimulateTransactionResponse; +declare type SendTx = SorobanRpc.SendTransactionResponse; +declare type GetTx = SorobanRpc.GetTransactionResponse; declare let someRpcResponse: Simulation | SendTx | GetTx; -type SomeRpcResponse = typeof someRpcResponse; -type InvokeArgs = MethodOptions & ClassOptions & { +declare type SomeRpcResponse = typeof someRpcResponse; +declare type InvokeArgs = MethodOptions & ClassOptions & { method: string; args?: any[]; parseResultXdr: (xdr: string | xdr.ScVal) => T; diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.js index 0ea2d1a4c..2b2830018 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.js +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/invoke.js @@ -1,4 +1,5 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; /** * Get account details from the Soroban network for the publicKey currently * selected in Freighter. If not connected to Freighter, return null. @@ -32,35 +33,28 @@ export async function invoke({ method, args = [], fee = 100, responseType, parse fee: fee.toString(10), networkPassphrase, }) + .setNetworkPassphrase(networkPassphrase) .addOperation(contract.call(method, ...args)) .setTimeout(SorobanClient.TimeoutInfinite) .build(); - console.log(method, args); const simulated = await server.simulateTransaction(tx); - console.log("---\n", simulated.result.retval, "\n----"); - if (simulated.error) - throw simulated.error; - if (responseType === "simulated") + if (SorobanRpc.isSimulationError(simulated)) { + throw new Error(simulated.error); + } + else if (responseType === "simulated") { return simulated; - // is it possible for `auths` to be present but empty? Probably not, but let's be safe. - let authsCount = simulated.result.auth?.length ?? 0; - const writeLength = simulated.transactionData - .build() - .resources() - .footprint() - .readWrite().length; - const isViewCall = authsCount === 0 && writeLength === 0; + } + else if (!simulated.result) { + throw new Error(`invalid simulation: no result in ${simulated}`); + } + let authsCount = simulated.result.auth.length; + const writeLength = simulated.transactionData.getReadWrite().length; + const isViewCall = (authsCount === 0) && (writeLength === 0); if (isViewCall) { - if (responseType === "full") + if (responseType === "full") { return simulated; - const retval = simulated.result?.retval; - if (!retval) { - if (simulated.error) { - throw new Error(simulated.error); - } - throw new Error(`Invalid response from simulateTransaction:\n{simulated}`); } - return parseResultXdr(retval); + return parseResultXdr(simulated.result.retval); } if (authsCount > 1) { throw new NotImplementedError("Multiple auths not yet supported"); @@ -80,15 +74,24 @@ export async function invoke({ method, args = [], fee = 100, responseType, parse } tx = await signTx(wallet, SorobanClient.assembleTransaction(tx, networkPassphrase, simulated).build(), networkPassphrase); const raw = await sendTx(tx, secondsToWait, server); - if (responseType === "full") + if (responseType === "full") { return raw; + } // if `sendTx` awaited the inclusion of the tx in the ledger, it used // `getTransaction`, which has a `resultXdr` field - if ("resultXdr" in raw) + if ("resultXdr" in raw) { + const getResult = raw; + if (getResult.status !== SorobanRpc.GetTransactionStatus.SUCCESS) { + console.error('Transaction submission failed! Returning full RPC response.'); + return raw; + } return parse(raw.resultXdr.result().toXDR("base64")); + } // otherwise, it returned the result of `sendTransaction` - if ("errorResultXdr" in raw) - return parse(raw.errorResultXdr); + if ("errorResultXdr" in raw) { + const sendResult = raw; + return parse(sendResult.errorResultXdr); + } // if neither of these are present, something went wrong console.error("Don't know how to parse result! Returning full RPC response."); return raw; @@ -127,7 +130,7 @@ export async function sendTx(tx, secondsToWait, server) { let waitTime = 1000; let exponentialFactor = 1.5; while (Date.now() < waitUntil && - getTransactionResponse.status === "NOT_FOUND") { + getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND) { // Wait a beat await new Promise((resolve) => setTimeout(resolve, waitTime)); /// Exponential backoff @@ -135,8 +138,10 @@ export async function sendTx(tx, secondsToWait, server) { // See if the transaction is complete getTransactionResponse = await server.getTransaction(sendTransactionResponse.hash); } - if (getTransactionResponse.status === "NOT_FOUND") { - console.error(`Waited ${secondsToWait} seconds for transaction to complete, but it did not. Returning anyway. Check the transaction status manually. Info: ${JSON.stringify(sendTransactionResponse, null, 2)}`); + if (getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND) { + console.error(`Waited ${secondsToWait} seconds for transaction to complete, but it did not. ` + + `Returning anyway. Check the transaction status manually. ` + + `Info: ${JSON.stringify(sendTransactionResponse, null, 2)}`); } return getTransactionResponse; } diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/method-options.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/method-options.d.ts index f861ff1f2..a959d97f2 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/method-options.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/esm/method-options.d.ts @@ -1,6 +1,6 @@ declare let responseTypes: 'simulated' | 'full' | undefined; -export type ResponseTypes = typeof responseTypes; -export type XDR_BASE64 = string; +export declare type ResponseTypes = typeof responseTypes; +export declare type XDR_BASE64 = string; export interface Wallet { isConnected: () => Promise; isAllowed: () => Promise; @@ -13,7 +13,7 @@ export interface Wallet { accountToSign?: string; }) => Promise; } -export type ClassOptions = { +export declare type ClassOptions = { contractId: string; networkPassphrase: string; rpcUrl: string; @@ -32,7 +32,7 @@ export type ClassOptions = { */ wallet?: Wallet; }; -export type MethodOptions = { +export declare type MethodOptions = { /** * The fee to pay for the transaction. Default: 100. */ diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/index.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/index.d.ts index 96512dce6..afc811097 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/index.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/index.d.ts @@ -4,17 +4,17 @@ import { Buffer } from "buffer"; import type { ResponseTypes, ClassOptions } from './method-options.js'; export * from './invoke.js'; export * from './method-options.js'; -export type u32 = number; -export type i32 = number; -export type u64 = bigint; -export type i64 = bigint; -export type u128 = bigint; -export type i128 = bigint; -export type u256 = bigint; -export type i256 = bigint; -export type Option = T | undefined; -export type Typepoint = bigint; -export type Duration = bigint; +export declare type u32 = number; +export declare type i32 = number; +export declare type u64 = bigint; +export declare type i64 = bigint; +export declare type u128 = bigint; +export declare type i128 = bigint; +export declare type u256 = bigint; +export declare type i256 = bigint; +export declare type Option = T | undefined; +export declare type Typepoint = bigint; +export declare type Duration = bigint; export { Address }; export interface Error_ { message: string; @@ -55,7 +55,7 @@ export interface Test { b: boolean; c: string; } -export type SimpleEnum = { +export declare type SimpleEnum = { tag: "First"; values: void; } | { @@ -70,8 +70,8 @@ export declare enum RoyalCard { Queen = 12, King = 13 } -export type TupleStruct = readonly [Test, SimpleEnum]; -export type ComplexEnum = { +export declare type TupleStruct = readonly [Test, SimpleEnum]; +export declare type ComplexEnum = { tag: "Struct"; values: readonly [Test]; } | { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/invoke.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/invoke.d.ts index 4e8e95394..1934a69a6 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/invoke.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/invoke.d.ts @@ -1,15 +1,16 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; import type { Memo, MemoType, Operation, Transaction, xdr } from "soroban-client"; import type { ClassOptions, MethodOptions, ResponseTypes, Wallet } from "./method-options.js"; -export type Tx = Transaction, Operation[]>; +export declare type Tx = Transaction, Operation[]>; export declare class NotImplementedError extends Error { } -type Simulation = SorobanClient.SorobanRpc.SimulateTransactionResponse; -type SendTx = SorobanClient.SorobanRpc.SendTransactionResponse; -type GetTx = SorobanClient.SorobanRpc.GetTransactionResponse; +declare type Simulation = SorobanRpc.SimulateTransactionResponse; +declare type SendTx = SorobanRpc.SendTransactionResponse; +declare type GetTx = SorobanRpc.GetTransactionResponse; declare let someRpcResponse: Simulation | SendTx | GetTx; -type SomeRpcResponse = typeof someRpcResponse; -type InvokeArgs = MethodOptions & ClassOptions & { +declare type SomeRpcResponse = typeof someRpcResponse; +declare type InvokeArgs = MethodOptions & ClassOptions & { method: string; args?: any[]; parseResultXdr: (xdr: string | xdr.ScVal) => T; diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/method-options.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/method-options.d.ts index f861ff1f2..a959d97f2 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/method-options.d.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/types/method-options.d.ts @@ -1,6 +1,6 @@ declare let responseTypes: 'simulated' | 'full' | undefined; -export type ResponseTypes = typeof responseTypes; -export type XDR_BASE64 = string; +export declare type ResponseTypes = typeof responseTypes; +export declare type XDR_BASE64 = string; export interface Wallet { isConnected: () => Promise; isAllowed: () => Promise; @@ -13,7 +13,7 @@ export interface Wallet { accountToSign?: string; }) => Promise; } -export type ClassOptions = { +export declare type ClassOptions = { contractId: string; networkPassphrase: string; rpcUrl: string; @@ -32,7 +32,7 @@ export type ClassOptions = { */ wallet?: Wallet; }; -export type MethodOptions = { +export declare type MethodOptions = { /** * The fee to pay for the transaction. Default: 100. */ diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json index d2c672a81..d2b02b5d1 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json @@ -1,7 +1,7 @@ { "name": "test_custom_types", "version": "0.0.0", - "lockfileVersion": 3, + "lockfileVersion": 2, "requires": true, "packages": { "": { @@ -10,7 +10,7 @@ "dependencies": { "@stellar/freighter-api": "1.5.1", "buffer": "6.0.3", - "soroban-client": "0.11.0" + "soroban-client": "1.0.0-beta.2" }, "devDependencies": { "typescript": "5.1.6" @@ -18,18 +18,15 @@ }, "node_modules/@stellar/freighter-api": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stellar/freighter-api/-/freighter-api-1.5.1.tgz", - "integrity": "sha512-WEnKEqd+xVLnOq6bJv+fLXod8JQyPjzpOKTpH4g7tG9MM1fmXzD3y2SXJlpCIw8kVqtiC4ynWOlSWX+TKO7KiQ==" + "license": "Apache-2.0" }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "license": "MIT" }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.5.0", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -46,8 +43,6 @@ }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -61,20 +56,19 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bignumber.js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", - "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", "engines": { "node": "*" } }, "node_modules/buffer": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -89,6 +83,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -96,8 +91,7 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -107,22 +101,20 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -134,8 +126,7 @@ }, "node_modules/form-data": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -147,8 +138,6 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -162,7 +151,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", @@ -176,16 +166,14 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -194,9 +182,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -206,8 +194,7 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "license": "MIT" }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -251,24 +238,24 @@ } }, "node_modules/soroban-client": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/soroban-client/-/soroban-client-0.11.0.tgz", - "integrity": "sha512-I7861W31Lruy57JaRsK9Hn78zX+VSVf9ocNoVQZBQTfYQ3fJF1tNqyeDXkmIwmBl2aljtgFOChqIl2cufh/8EA==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/soroban-client/-/soroban-client-1.0.0-beta.2.tgz", + "integrity": "sha512-v5h3yvef7HkUD3H26w33NUEgRXcPiOSDWEsVzMloaxsprs3N002tXJHvFF+Uw1eYt50Uk6bvqBgvkLwX10VENw==", "dependencies": { "axios": "^1.4.0", "bignumber.js": "^9.1.1", "buffer": "^6.0.3", - "stellar-base": "10.0.0-soroban.7", + "stellar-base": "v10.0.0-beta.1", "urijs": "^1.19.1" } }, "node_modules/stellar-base": { - "version": "10.0.0-soroban.7", - "resolved": "https://registry.npmjs.org/stellar-base/-/stellar-base-10.0.0-soroban.7.tgz", - "integrity": "sha512-5+qqGsFXagtbG0L/oIiTDEIUsnerE7Vwvv/Hp2ugG0sKulcnfxgYjNqeon3Zv13uoJ4dtjslQpVOzLxPlklViQ==", + "version": "10.0.0-beta.1", + "resolved": "https://registry.npmjs.org/stellar-base/-/stellar-base-10.0.0-beta.1.tgz", + "integrity": "sha512-zXC5AsbUsLi57JruyeIMv23s3iUxq/P2ZFrSJ+FerLIZjSAjY8EDs4zwY4LCuu7swUu46Lm8GK6sqxUZCPekHw==", "dependencies": { "base32.js": "^0.1.0", - "bignumber.js": "^9.1.1", + "bignumber.js": "^9.1.2", "buffer": "^6.0.3", "js-xdr": "^3.0.0", "sha.js": "^2.3.6", @@ -285,9 +272,8 @@ }, "node_modules/typescript": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -298,8 +284,155 @@ }, "node_modules/urijs": { "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" + "license": "MIT" + } + }, + "dependencies": { + "@stellar/freighter-api": { + "version": "1.5.1" + }, + "asynckit": { + "version": "0.4.0" + }, + "axios": { + "version": "1.5.0", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==" + }, + "base64-js": { + "version": "1.5.1" + }, + "bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" + }, + "buffer": { + "version": "6.0.3", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "combined-stream": { + "version": "1.0.8", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0" + }, + "follow-redirects": { + "version": "1.15.2" + }, + "form-data": { + "version": "4.0.0", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "ieee754": { + "version": "1.2.1" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "js-xdr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js-xdr/-/js-xdr-3.0.0.tgz", + "integrity": "sha512-tSt6UKJ2L7t+yaQURGkHo9kop9qnVbChTlCu62zNiDbDZQoZb/YjUj2iFJ3lgelhfg9p5bhO2o/QX+g36TPsSQ==" + }, + "mime-db": { + "version": "1.52.0" + }, + "mime-types": { + "version": "2.1.35", + "requires": { + "mime-db": "1.52.0" + } + }, + "node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "optional": true + }, + "proxy-from-env": { + "version": "1.1.0" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "sodium-native": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.0.4.tgz", + "integrity": "sha512-faqOKw4WQKK7r/ybn6Lqo1F9+L5T6NlBJJYvpxbZPetpWylUVqz449mvlwIBKBqxEHbWakWuOlUt8J3Qpc4sWw==", + "optional": true, + "requires": { + "node-gyp-build": "^4.6.0" + } + }, + "soroban-client": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/soroban-client/-/soroban-client-1.0.0-beta.2.tgz", + "integrity": "sha512-v5h3yvef7HkUD3H26w33NUEgRXcPiOSDWEsVzMloaxsprs3N002tXJHvFF+Uw1eYt50Uk6bvqBgvkLwX10VENw==", + "requires": { + "axios": "^1.4.0", + "bignumber.js": "^9.1.1", + "buffer": "^6.0.3", + "stellar-base": "v10.0.0-beta.1", + "urijs": "^1.19.1" + } + }, + "stellar-base": { + "version": "10.0.0-beta.1", + "resolved": "https://registry.npmjs.org/stellar-base/-/stellar-base-10.0.0-beta.1.tgz", + "integrity": "sha512-zXC5AsbUsLi57JruyeIMv23s3iUxq/P2ZFrSJ+FerLIZjSAjY8EDs4zwY4LCuu7swUu46Lm8GK6sqxUZCPekHw==", + "requires": { + "base32.js": "^0.1.0", + "bignumber.js": "^9.1.2", + "buffer": "^6.0.3", + "js-xdr": "^3.0.0", + "sha.js": "^2.3.6", + "sodium-native": "^4.0.1", + "tweetnacl": "^1.0.3" + } + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "typescript": { + "version": "5.1.6", + "dev": true + }, + "urijs": { + "version": "1.19.11" } } } diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json index 01c222435..efb3acfe2 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json @@ -4,7 +4,7 @@ "dependencies": { "@stellar/freighter-api": "1.5.1", "buffer": "6.0.3", - "soroban-client": "0.11.0" + "soroban-client": "1.0.0-beta.2" }, "scripts": { "build": "node ./scripts/build.mjs" diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/convert.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/convert.ts index bf5f0aeff..ec3087c11 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/convert.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/convert.ts @@ -1,8 +1,13 @@ -import { Address, xdr, scValToBigInt, ScInt } from 'soroban-client'; -import { Buffer } from "buffer"; +import { + xdr, + Address, + nativeToScVal, + scValToBigInt, + ScInt +} from 'soroban-client'; export function strToScVal(base64Xdr: string): xdr.ScVal { - return xdr.ScVal.fromXDR(Buffer.from(base64Xdr, 'base64')); + return xdr.ScVal.fromXDR(base64Xdr, 'base64'); } export function scValStrToJs(base64Xdr: string): T { @@ -78,13 +83,10 @@ export function scValToJs(val: xdr.ScVal): T { return res as unknown as T } case xdr.ScValType.scvContractInstance(): - return val.instance() as unknown as T; case xdr.ScValType.scvLedgerKeyNonce(): - return val.nonceKey() as unknown as T; case xdr.ScValType.scvTimepoint(): - return val.timepoint() as unknown as T; case xdr.ScValType.scvDuration(): - return val.duration() as unknown as T; + return val.value() as unknown as T; // TODO: Add this case when merged // case xdr.ScValType.scvError(): default: { @@ -98,8 +100,7 @@ type KeyType = T extends Map ? K : never; type ValueType = T extends Map ? V : never; export function addressToScVal(addr: string): xdr.ScVal { - let addrObj = Address.fromString(addr); - return addrObj.toScVal(); + return nativeToScVal(addr, { type: 'address' } as any /* bug workaround */); } export function i128ToScVal(i: bigint): xdr.ScVal { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts index 07186bd45..5cce69fe0 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts @@ -277,7 +277,6 @@ export class Contract { }, }); } catch (e) { - console.log(e) if (typeof e === 'string') { let err = parseError(e); if (err) return err; diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/invoke.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/invoke.ts index 41c300144..93f823f1f 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/invoke.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/invoke.ts @@ -1,4 +1,5 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; import type { Account, Memo, @@ -36,9 +37,9 @@ async function getAccount( export class NotImplementedError extends Error {} -type Simulation = SorobanClient.SorobanRpc.SimulateTransactionResponse; -type SendTx = SorobanClient.SorobanRpc.SendTransactionResponse; -type GetTx = SorobanClient.SorobanRpc.GetTransactionResponse; +type Simulation = SorobanRpc.SimulateTransactionResponse; +type SendTx = SorobanRpc.SendTransactionResponse; +type GetTx = SorobanRpc.GetTransactionResponse; // defined this way so typeahead shows full union, not named alias let someRpcResponse: Simulation | SendTx | GetTx; @@ -102,38 +103,30 @@ export async function invoke({ fee: fee.toString(10), networkPassphrase, }) + .setNetworkPassphrase(networkPassphrase) .addOperation(contract.call(method, ...args)) .setTimeout(SorobanClient.TimeoutInfinite) .build(); const simulated = await server.simulateTransaction(tx); - if (simulated.error) throw simulated.error; - if (responseType === "simulated") return simulated; - - // is it possible for `auths` to be present but empty? Probably not, but let's be safe. - let authsCount = simulated.result.auth?.length ?? 0; - - const writeLength = simulated.transactionData - .build() - .resources() - .footprint() - .readWrite().length; + if (SorobanRpc.isSimulationError(simulated)) { + throw new Error(simulated.error); + } else if (responseType === "simulated") { + return simulated; + } else if (!simulated.result) { + throw new Error(`invalid simulation: no result in ${simulated}`); + } - const isViewCall = authsCount === 0 && writeLength === 0; + let authsCount = simulated.result.auth.length; + const writeLength = simulated.transactionData.getReadWrite().length; + const isViewCall = (authsCount === 0) && (writeLength === 0); if (isViewCall) { - if (responseType === "full") return simulated; - - const retval = simulated.result?.retval; - if (!retval) { - if (simulated.error) { - throw new Error(simulated.error as unknown as string); - } - throw new Error( - `Invalid response from simulateTransaction:\n{simulated}` - ); + if (responseType === "full") { + return simulated; } - return parseResultXdr(retval); + + return parseResultXdr(simulated.result.retval); } if (authsCount > 1) { @@ -161,15 +154,27 @@ export async function invoke({ ); const raw = await sendTx(tx, secondsToWait, server); - - if (responseType === "full") return raw; + if (responseType === "full") { + return raw; + } // if `sendTx` awaited the inclusion of the tx in the ledger, it used // `getTransaction`, which has a `resultXdr` field - if ("resultXdr" in raw) return parse(raw.resultXdr.result().toXDR("base64")); + if ("resultXdr" in raw) { + const getResult = raw as SorobanRpc.GetTransactionResponse; + if (getResult.status !== SorobanRpc.GetTransactionStatus.SUCCESS) { + console.error('Transaction submission failed! Returning full RPC response.'); + return raw; + } + + return parse(raw.resultXdr.result().toXDR("base64")); + } // otherwise, it returned the result of `sendTransaction` - if ("errorResultXdr" in raw) return parse(raw.errorResultXdr); + if ("errorResultXdr" in raw) { + const sendResult = raw as SorobanRpc.SendTransactionResponse; + return parse(sendResult.errorResultXdr); + } // if neither of these are present, something went wrong console.error("Don't know how to parse result! Returning full RPC response."); @@ -231,7 +236,7 @@ export async function sendTx( while ( Date.now() < waitUntil && - getTransactionResponse.status === "NOT_FOUND" + getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND ) { // Wait a beat await new Promise((resolve) => setTimeout(resolve, waitTime)); @@ -243,9 +248,13 @@ export async function sendTx( ); } - if (getTransactionResponse.status === "NOT_FOUND") { + if (getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND) { console.error( - `Waited ${secondsToWait} seconds for transaction to complete, but it did not. Returning anyway. Check the transaction status manually. Info: ${JSON.stringify( + `Waited ${ + secondsToWait + } seconds for transaction to complete, but it did not. ` + + `Returning anyway. Check the transaction status manually. ` + + `Info: ${JSON.stringify( sendTransactionResponse, null, 2 diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index fee02b05a..20d517a2a 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -145,7 +145,7 @@ mod test { p.init( "test_custom_types", "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", - "https://rpc-futurenet.stellar.org:443/soroban/rpc", + "https://rpc-futurenet.stellar.org:443", "Test SDF Future Network ; October 2022", &spec, ) diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/package.json b/cmd/crates/soroban-spec-typescript/src/project_template/package.json index 50f019a65..168e94258 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/package.json +++ b/cmd/crates/soroban-spec-typescript/src/project_template/package.json @@ -4,7 +4,7 @@ "dependencies": { "@stellar/freighter-api": "1.5.1", "buffer": "6.0.3", - "soroban-client": "0.11.0" + "soroban-client": "1.0.0-beta.2" }, "scripts": { "build": "node ./scripts/build.mjs" diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/src/convert.ts b/cmd/crates/soroban-spec-typescript/src/project_template/src/convert.ts index bf5f0aeff..ec3087c11 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/src/convert.ts +++ b/cmd/crates/soroban-spec-typescript/src/project_template/src/convert.ts @@ -1,8 +1,13 @@ -import { Address, xdr, scValToBigInt, ScInt } from 'soroban-client'; -import { Buffer } from "buffer"; +import { + xdr, + Address, + nativeToScVal, + scValToBigInt, + ScInt +} from 'soroban-client'; export function strToScVal(base64Xdr: string): xdr.ScVal { - return xdr.ScVal.fromXDR(Buffer.from(base64Xdr, 'base64')); + return xdr.ScVal.fromXDR(base64Xdr, 'base64'); } export function scValStrToJs(base64Xdr: string): T { @@ -78,13 +83,10 @@ export function scValToJs(val: xdr.ScVal): T { return res as unknown as T } case xdr.ScValType.scvContractInstance(): - return val.instance() as unknown as T; case xdr.ScValType.scvLedgerKeyNonce(): - return val.nonceKey() as unknown as T; case xdr.ScValType.scvTimepoint(): - return val.timepoint() as unknown as T; case xdr.ScValType.scvDuration(): - return val.duration() as unknown as T; + return val.value() as unknown as T; // TODO: Add this case when merged // case xdr.ScValType.scvError(): default: { @@ -98,8 +100,7 @@ type KeyType = T extends Map ? K : never; type ValueType = T extends Map ? V : never; export function addressToScVal(addr: string): xdr.ScVal { - let addrObj = Address.fromString(addr); - return addrObj.toScVal(); + return nativeToScVal(addr, { type: 'address' } as any /* bug workaround */); } export function i128ToScVal(i: bigint): xdr.ScVal { diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/src/invoke.ts b/cmd/crates/soroban-spec-typescript/src/project_template/src/invoke.ts index 41c300144..5bcd7d80f 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/src/invoke.ts +++ b/cmd/crates/soroban-spec-typescript/src/project_template/src/invoke.ts @@ -1,4 +1,5 @@ import * as SorobanClient from "soroban-client"; +import { SorobanRpc } from "soroban-client"; import type { Account, Memo, @@ -36,9 +37,9 @@ async function getAccount( export class NotImplementedError extends Error {} -type Simulation = SorobanClient.SorobanRpc.SimulateTransactionResponse; -type SendTx = SorobanClient.SorobanRpc.SendTransactionResponse; -type GetTx = SorobanClient.SorobanRpc.GetTransactionResponse; +type Simulation = SorobanRpc.SimulateTransactionResponse; +type SendTx = SorobanRpc.SendTransactionResponse; +type GetTx = SorobanRpc.GetTransactionResponse; // defined this way so typeahead shows full union, not named alias let someRpcResponse: Simulation | SendTx | GetTx; @@ -107,33 +108,24 @@ export async function invoke({ .build(); const simulated = await server.simulateTransaction(tx); - if (simulated.error) throw simulated.error; - if (responseType === "simulated") return simulated; - - // is it possible for `auths` to be present but empty? Probably not, but let's be safe. - let authsCount = simulated.result.auth?.length ?? 0; - - const writeLength = simulated.transactionData - .build() - .resources() - .footprint() - .readWrite().length; + if (SorobanRpc.isSimulationError(simulated)) { + throw new Error(simulated.error); + } else if (responseType === "simulated") { + return simulated; + } else if (!simulated.result) { + throw new Error(`invalid simulation: no result in ${simulated}`); + } - const isViewCall = authsCount === 0 && writeLength === 0; + let authsCount = simulated.result.auth.length; + const writeLength = simulated.transactionData.getReadWrite().length; + const isViewCall = (authsCount === 0) && (writeLength === 0); if (isViewCall) { - if (responseType === "full") return simulated; - - const retval = simulated.result?.retval; - if (!retval) { - if (simulated.error) { - throw new Error(simulated.error as unknown as string); - } - throw new Error( - `Invalid response from simulateTransaction:\n{simulated}` - ); + if (responseType === "full") { + return simulated; } - return parseResultXdr(retval); + + return parseResultXdr(simulated.result.retval); } if (authsCount > 1) { @@ -161,15 +153,27 @@ export async function invoke({ ); const raw = await sendTx(tx, secondsToWait, server); - - if (responseType === "full") return raw; + if (responseType === "full") { + return raw; + } // if `sendTx` awaited the inclusion of the tx in the ledger, it used // `getTransaction`, which has a `resultXdr` field - if ("resultXdr" in raw) return parse(raw.resultXdr.result().toXDR("base64")); + if ("resultXdr" in raw) { + const getResult = raw as SorobanRpc.GetTransactionResponse; + if (getResult.status !== SorobanRpc.GetTransactionStatus.SUCCESS) { + console.error('Transaction submission failed! Returning full RPC response.'); + return raw; + } + + return parse(raw.resultXdr.result().toXDR("base64")); + } // otherwise, it returned the result of `sendTransaction` - if ("errorResultXdr" in raw) return parse(raw.errorResultXdr); + if ("errorResultXdr" in raw) { + const sendResult = raw as SorobanRpc.SendTransactionResponse; + return parse(sendResult.errorResultXdr); + } // if neither of these are present, something went wrong console.error("Don't know how to parse result! Returning full RPC response."); @@ -231,7 +235,7 @@ export async function sendTx( while ( Date.now() < waitUntil && - getTransactionResponse.status === "NOT_FOUND" + getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND ) { // Wait a beat await new Promise((resolve) => setTimeout(resolve, waitTime)); @@ -243,9 +247,13 @@ export async function sendTx( ); } - if (getTransactionResponse.status === "NOT_FOUND") { + if (getTransactionResponse.status === SorobanRpc.GetTransactionStatus.NOT_FOUND) { console.error( - `Waited ${secondsToWait} seconds for transaction to complete, but it did not. Returning anyway. Check the transaction status manually. Info: ${JSON.stringify( + `Waited ${ + secondsToWait + } seconds for transaction to complete, but it did not. ` + + `Returning anyway. Check the transaction status manually. ` + + `Info: ${JSON.stringify( sendTransactionResponse, null, 2