From 4dd685d3a5682918fe066fa2f69a2ca68c911b12 Mon Sep 17 00:00:00 2001 From: Zach Fedor Date: Wed, 8 Oct 2025 20:00:11 -0400 Subject: [PATCH 1/5] feat: replace standalone with local --- .../src/boilerplate.rs | 4 +- .../ts-tests/src/test-custom-types.ts | 338 ++++++++++-------- .../src/test-deserialized-transaction.ts | 20 +- .../ts-tests/src/test-xlm-lib-from-sac.ts | 10 +- 4 files changed, 201 insertions(+), 171 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index a4e2465828..c717317df6 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -14,7 +14,7 @@ static PROJECT_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/src/project_temp const NETWORK_PASSPHRASE_TESTNET: &str = "Test SDF Network ; September 2015"; const NETWORK_PASSPHRASE_FUTURENET: &str = "Test SDF Future Network ; October 2022"; -const NETWORK_PASSPHRASE_STANDALONE: &str = "Standalone Network ; February 2017"; +const NETWORK_PASSPHRASE_LOCAL: &str = "Standalone Network ; February 2017"; pub struct Project(PathBuf); @@ -125,7 +125,7 @@ impl Project { let network = match network_passphrase { NETWORK_PASSPHRASE_TESTNET => "testnet", NETWORK_PASSPHRASE_FUTURENET => "futurenet", - NETWORK_PASSPHRASE_STANDALONE => "standalone", + NETWORK_PASSPHRASE_LOCAL => "local", _ => "unknown", }; format!( diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts index 1f808aafbe..3a718c04f4 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts @@ -1,193 +1,223 @@ -import test from 'ava' -import { root, rpcUrl, signer } from './util.js' -import { Client, networks, contract as ContractClient } from 'test-custom-types' +import test from "ava"; +import { root, rpcUrl, signer } from "./util.js"; +import { + Client, + networks, + contract as ContractClient, +} from "test-custom-types"; const publicKey = root.keypair.publicKey(); const contract = new Client({ - ...networks.standalone, + ...networks.local, rpcUrl, allowHttp: true, publicKey: root.keypair.publicKey(), ...signer, }); -test('hello', async t => { - const { result } = await contract.hello({ hello: 'tests' }) - t.is(result, 'tests') -}) +test("hello", async (t) => { + const { result } = await contract.hello({ hello: "tests" }); + t.is(result, "tests"); +}); -test('woid', async t => { - t.is((await contract.woid()).result, null) -}) +test("woid", async (t) => { + t.is((await contract.woid()).result, null); +}); -test('u32_fail_on_even', async t => { +test("u32_fail_on_even", async (t) => { t.deepEqual( (await contract.u32_fail_on_even({ u32_: 1 })).result, - new ContractClient.Ok(1) - ) + new ContractClient.Ok(1), + ); t.deepEqual( (await contract.u32_fail_on_even({ u32_: 0 })).result, - new ContractClient.Err({ message: "Please provide an odd number" }) - ) -}) + new ContractClient.Err({ message: "Please provide an odd number" }), + ); +}); -test('u32_', async t => { - t.is((await contract.u32_({ u32_: 1 })).result, 1) -}) +test("u32_", async (t) => { + t.is((await contract.u32_({ u32_: 1 })).result, 1); +}); -test('i32_', async t => { - t.is((await contract.i32_({ i32_: 1 })).result, 1) -}) +test("i32_", async (t) => { + t.is((await contract.i32_({ i32_: 1 })).result, 1); +}); -test('i64_', async t => { - t.is((await contract.i64_({ i64_: 1n })).result, 1n) -}) +test("i64_", async (t) => { + t.is((await contract.i64_({ i64_: 1n })).result, 1n); +}); test("strukt_hel", async (t) => { - const test = { a: 0, b: true, c: "world" } - t.deepEqual((await contract.strukt_hel({ strukt: test })).result, ["Hello", "world"]) -}) + const test = { a: 0, b: true, c: "world" }; + t.deepEqual((await contract.strukt_hel({ strukt: test })).result, [ + "Hello", + "world", + ]); +}); test("strukt", async (t) => { - const test = { a: 0, b: true, c: "hello" } - t.deepEqual((await contract.strukt({ strukt: test })).result, test) -}) - -test('simple first', async t => { - const arg = { tag: 'First', values: undefined } as const - const ret = { tag: 'First' } - t.deepEqual((await contract.simple({ simple: arg })).result, ret) -}) - -test('simple second', async t => { - const arg = { tag: 'Second', values: undefined } as const - const ret = { tag: 'Second' } - t.deepEqual((await contract.simple({ simple: arg })).result, ret) -}) - -test('simple third', async t => { - const arg = { tag: 'Third', values: undefined } as const - const ret = { tag: 'Third' } - t.deepEqual((await contract.simple({ simple: arg })).result, ret) -}) - -test('complex with struct', async t => { - const arg = { tag: 'Struct', values: [{ a: 0, b: true, c: 'hello' }] } as const - const ret = { tag: 'Struct', values: [{ a: 0, b: true, c: 'hello' }] } - t.deepEqual((await contract.complex({ complex: arg })).result, ret) -}) - -test('complex with tuple', async t => { - const arg = { tag: 'Tuple', values: [[{ a: 0, b: true, c: 'hello' }, { tag: 'First', values: undefined }]] } as const - const ret = { tag: 'Tuple', values: [[{ a: 0, b: true, c: 'hello' }, { tag: 'First' }]] } - t.deepEqual((await contract.complex({ complex: arg })).result, ret) -}) - -test('complex with enum', async t => { - const arg = { tag: 'Enum', values: [{ tag: 'First', values: undefined }] } as const - const ret = { tag: 'Enum', values: [{ tag: 'First' }] } - t.deepEqual((await contract.complex({ complex: arg })).result, ret) -}) - -test('complex with asset', async t => { - const arg = { tag: 'Asset', values: [publicKey, 1n] } as const - const ret = { tag: 'Asset', values: [publicKey, 1n] } - t.deepEqual((await contract.complex({ complex: arg })).result, ret) -}) - -test('complex with void', async t => { - const arg = { tag: 'Void', values: undefined } as const - const ret = { tag: 'Void' } - t.deepEqual((await contract.complex({ complex: arg })).result, ret) -}) - -test('addresse', async t => { - t.deepEqual((await contract.addresse({ addresse: publicKey })).result, publicKey) -}) - -test('bytes', async t => { - const bytes = Buffer.from('hello') - t.deepEqual((await contract.bytes({ bytes })).result, bytes) -}) - -test('bytes_n', async t => { - const bytes_n = Buffer.from('123456789') // what's the correct way to construct bytes_n? - t.deepEqual((await contract.bytes_n({ bytes_n })).result, bytes_n) -}) - -test('card', async t => { - const card = 11 - t.is((await contract.card({ card })).result, card) -}) - -test('boolean', async t => { - t.is((await contract.boolean({ boolean: true })).result, true) -}) - -test('not', async t => { - t.is((await contract.not({ boolean: true })).result, false) -}) - -test('i128', async t => { - t.is((await contract.i128({ i128: -1n })).result, -1n) -}) - -test('u128', async t => { - t.is((await contract.u128({ u128: 1n })).result, 1n) -}) - -test('multi_args', async t => { - t.is((await contract.multi_args({ a: 1, b: true })).result, 1) - t.is((await contract.multi_args({ a: 1, b: false })).result, 0) -}) - -test('map', async t => { - const map = new Map() - map.set(1, true) - map.set(2, false) + const test = { a: 0, b: true, c: "hello" }; + t.deepEqual((await contract.strukt({ strukt: test })).result, test); +}); + +test("simple first", async (t) => { + const arg = { tag: "First", values: undefined } as const; + const ret = { tag: "First" }; + t.deepEqual((await contract.simple({ simple: arg })).result, ret); +}); + +test("simple second", async (t) => { + const arg = { tag: "Second", values: undefined } as const; + const ret = { tag: "Second" }; + t.deepEqual((await contract.simple({ simple: arg })).result, ret); +}); + +test("simple third", async (t) => { + const arg = { tag: "Third", values: undefined } as const; + const ret = { tag: "Third" }; + t.deepEqual((await contract.simple({ simple: arg })).result, ret); +}); + +test("complex with struct", async (t) => { + const arg = { + tag: "Struct", + values: [{ a: 0, b: true, c: "hello" }], + } as const; + const ret = { tag: "Struct", values: [{ a: 0, b: true, c: "hello" }] }; + t.deepEqual((await contract.complex({ complex: arg })).result, ret); +}); + +test("complex with tuple", async (t) => { + const arg = { + tag: "Tuple", + values: [ + [ + { a: 0, b: true, c: "hello" }, + { tag: "First", values: undefined }, + ], + ], + } as const; + const ret = { + tag: "Tuple", + values: [[{ a: 0, b: true, c: "hello" }, { tag: "First" }]], + }; + t.deepEqual((await contract.complex({ complex: arg })).result, ret); +}); + +test("complex with enum", async (t) => { + const arg = { + tag: "Enum", + values: [{ tag: "First", values: undefined }], + } as const; + const ret = { tag: "Enum", values: [{ tag: "First" }] }; + t.deepEqual((await contract.complex({ complex: arg })).result, ret); +}); + +test("complex with asset", async (t) => { + const arg = { tag: "Asset", values: [publicKey, 1n] } as const; + const ret = { tag: "Asset", values: [publicKey, 1n] }; + t.deepEqual((await contract.complex({ complex: arg })).result, ret); +}); + +test("complex with void", async (t) => { + const arg = { tag: "Void", values: undefined } as const; + const ret = { tag: "Void" }; + t.deepEqual((await contract.complex({ complex: arg })).result, ret); +}); + +test("addresse", async (t) => { + t.deepEqual( + (await contract.addresse({ addresse: publicKey })).result, + publicKey, + ); +}); + +test("bytes", async (t) => { + const bytes = Buffer.from("hello"); + t.deepEqual((await contract.bytes({ bytes })).result, bytes); +}); + +test("bytes_n", async (t) => { + const bytes_n = Buffer.from("123456789"); // what's the correct way to construct bytes_n? + t.deepEqual((await contract.bytes_n({ bytes_n })).result, bytes_n); +}); + +test("card", async (t) => { + const card = 11; + t.is((await contract.card({ card })).result, card); +}); + +test("boolean", async (t) => { + t.is((await contract.boolean({ boolean: true })).result, true); +}); + +test("not", async (t) => { + t.is((await contract.not({ boolean: true })).result, false); +}); + +test("i128", async (t) => { + t.is((await contract.i128({ i128: -1n })).result, -1n); +}); + +test("u128", async (t) => { + t.is((await contract.u128({ u128: 1n })).result, 1n); +}); + +test("multi_args", async (t) => { + t.is((await contract.multi_args({ a: 1, b: true })).result, 1); + t.is((await contract.multi_args({ a: 1, b: false })).result, 0); +}); + +test("map", async (t) => { + const map = new Map(); + map.set(1, true); + map.set(2, false); // map.set(3, 'hahaha') // should throw an error - const ret = Array.from(map.entries()) - t.deepEqual((await contract.map({ map })).result, ret) -}) + const ret = Array.from(map.entries()); + t.deepEqual((await contract.map({ map })).result, ret); +}); -test('vec', async t => { - const vec = [1, 2, 3] - t.deepEqual((await contract.vec({ vec })).result, vec) -}) +test("vec", async (t) => { + const vec = [1, 2, 3]; + t.deepEqual((await contract.vec({ vec })).result, vec); +}); -test('tuple', async t => { - const tuple = ['hello', 1] as const - t.deepEqual((await contract.tuple({ tuple })).result, tuple) -}) +test("tuple", async (t) => { + const tuple = ["hello", 1] as const; + t.deepEqual((await contract.tuple({ tuple })).result, tuple); +}); -test('option', async t => { +test("option", async (t) => { // this makes sense - t.deepEqual((await contract.option({ option: 1 })).result, 1) + t.deepEqual((await contract.option({ option: 1 })).result, 1); // this passes but shouldn't - t.deepEqual((await contract.option({ option: undefined })).result, undefined) + t.deepEqual((await contract.option({ option: undefined })).result, undefined); // this is the behavior we probably want, but fails // t.deepEqual(await contract.option(), undefined) // typing and implementation require the object // t.deepEqual((await contract.option({})).result, undefined) // typing requires argument; implementation would be fine with this // t.deepEqual((await contract.option({ option: undefined })).result, undefined) -}) +}); -test('u256', async t => { - t.is((await contract.u256({ u256: 1n })).result, 1n) -}) +test("u256", async (t) => { + t.is((await contract.u256({ u256: 1n })).result, 1n); +}); -test('i256', async t => { - t.is((await contract.i256({ i256: -1n })).result, -1n) -}) +test("i256", async (t) => { + t.is((await contract.i256({ i256: -1n })).result, -1n); +}); -test('string', async t => { - t.is((await contract.string({ string: 'hello' })).result, 'hello') -}) +test("string", async (t) => { + t.is((await contract.string({ string: "hello" })).result, "hello"); +}); -test('tuple_strukt', async t => { - const arg = [{ a: 0, b: true, c: 'hello' }, { tag: 'First', values: undefined }] as const - const res = [{ a: 0, b: true, c: 'hello' }, { tag: 'First' }] - t.deepEqual((await contract.tuple_strukt({ tuple_strukt: arg })).result, res) -}) +test("tuple_strukt", async (t) => { + const arg = [ + { a: 0, b: true, c: "hello" }, + { tag: "First", values: undefined }, + ] as const; + const res = [{ a: 0, b: true, c: "hello" }, { tag: "First" }]; + t.deepEqual((await contract.tuple_strukt({ tuple_strukt: arg })).result, res); +}); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts index 1208c65c73..922c023d10 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts @@ -1,20 +1,20 @@ -import test from "ava" -import { rpcUrl, root, signer } from "./util.js" -import { Client, networks } from "test-custom-types" +import test from "ava"; +import { rpcUrl, root, signer } from "./util.js"; +import { Client, networks } from "test-custom-types"; const contract = new Client({ - ...networks.standalone, + ...networks.local, rpcUrl, allowHttp: true, publicKey: root.keypair.publicKey(), ...signer, -}) +}); test("has correctly-typed result", async (t) => { - const initial = await contract.hello({ hello: "tests" }) - t.is(initial.result, "tests") + const initial = await contract.hello({ hello: "tests" }); + t.is(initial.result, "tests"); - const serialized = initial.toJSON() - const deserialized = contract.fromJSON.hello(serialized) - t.is(deserialized.result, "tests") // throws TS error if `result` is of type `unknown` + const serialized = initial.toJSON(); + const deserialized = contract.fromJSON.hello(serialized); + t.is(deserialized.result, "tests"); // throws TS error if `result` is of type `unknown` }); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts index e39fb8b7de..143a898b3f 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts @@ -1,14 +1,14 @@ -import test from "ava" -import { rpcUrl, root, signer } from "./util.js" -import { Client, networks } from "xlm" +import test from "ava"; +import { rpcUrl, root, signer } from "./util.js"; +import { Client, networks } from "xlm"; const contract = new Client({ - ...networks.standalone, + ...networks.local, rpcUrl, allowHttp: true, publicKey: root.keypair.publicKey(), ...signer, -}) +}); test("can generate a lib from a Stellar Asset Contract", async (t) => { t.is((await contract.symbol()).result, "native"); From 8e213010e3ef7f1c1cccca28d090e51c47a029f5 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 6 May 2026 03:07:25 +0000 Subject: [PATCH 2/5] revert unrelated formatting in ts tests --- .../ts-tests/src/test-custom-types.ts | 12 +++++++++--- .../src/test-deserialized-transaction.ts | 18 +++++++++--------- .../ts-tests/src/test-xlm-lib-from-sac.ts | 8 ++++---- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts index 3a718c04f4..40e78e48a2 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts @@ -189,11 +189,9 @@ test("tuple", async (t) => { }); test("option", async (t) => { - // this makes sense t.deepEqual((await contract.option({ option: 1 })).result, 1); - // this passes but shouldn't - t.deepEqual((await contract.option({ option: undefined })).result, undefined); + t.deepEqual((await contract.option({ option: undefined })).result, null); // this is the behavior we probably want, but fails // t.deepEqual(await contract.option(), undefined) // typing and implementation require the object @@ -221,3 +219,11 @@ test("tuple_strukt", async (t) => { const res = [{ a: 0, b: true, c: "hello" }, { tag: "First" }]; t.deepEqual((await contract.tuple_strukt({ tuple_strukt: arg })).result, res); }); + +test("timepoint", async (t) => { + t.is((await contract.timepoint({ timepoint: 1n })).result, 1n); +}); + +test("duration", async (t) => { + t.is((await contract.duration({ duration: 1n })).result, 1n); +}); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts index 922c023d10..e49ad5f112 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-deserialized-transaction.ts @@ -1,6 +1,6 @@ -import test from "ava"; -import { rpcUrl, root, signer } from "./util.js"; -import { Client, networks } from "test-custom-types"; +import test from "ava" +import { rpcUrl, root, signer } from "./util.js" +import { Client, networks } from "test-custom-types" const contract = new Client({ ...networks.local, @@ -8,13 +8,13 @@ const contract = new Client({ allowHttp: true, publicKey: root.keypair.publicKey(), ...signer, -}); +}) test("has correctly-typed result", async (t) => { - const initial = await contract.hello({ hello: "tests" }); - t.is(initial.result, "tests"); + const initial = await contract.hello({ hello: "tests" }) + t.is(initial.result, "tests") - const serialized = initial.toJSON(); - const deserialized = contract.fromJSON.hello(serialized); - t.is(deserialized.result, "tests"); // throws TS error if `result` is of type `unknown` + const serialized = initial.toJSON() + const deserialized = contract.fromJSON.hello(serialized) + t.is(deserialized.result, "tests") // throws TS error if `result` is of type `unknown` }); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts index 143a898b3f..38144fa5a2 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts @@ -1,6 +1,6 @@ -import test from "ava"; -import { rpcUrl, root, signer } from "./util.js"; -import { Client, networks } from "xlm"; +import test from "ava" +import { rpcUrl, root, signer } from "./util.js" +import { Client, networks } from "xlm" const contract = new Client({ ...networks.local, @@ -8,7 +8,7 @@ const contract = new Client({ allowHttp: true, publicKey: root.keypair.publicKey(), ...signer, -}); +}) test("can generate a lib from a Stellar Asset Contract", async (t) => { t.is((await contract.symbol()).result, "native"); From c561884d4a55ddb6a1387fdd873fbd82cddf7487 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 6 May 2026 03:13:32 +0000 Subject: [PATCH 3/5] restore original ts test formatting --- .../ts-tests/src/test-custom-types.ts | 346 ++++++++---------- 1 file changed, 155 insertions(+), 191 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts index 40e78e48a2..7d36feb78f 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-custom-types.ts @@ -1,10 +1,6 @@ -import test from "ava"; -import { root, rpcUrl, signer } from "./util.js"; -import { - Client, - networks, - contract as ContractClient, -} from "test-custom-types"; +import test from 'ava' +import { root, rpcUrl, signer } from './util.js' +import { Client, networks, contract as ContractClient } from 'test-custom-types' const publicKey = root.keypair.publicKey(); @@ -16,214 +12,182 @@ const contract = new Client({ ...signer, }); -test("hello", async (t) => { - const { result } = await contract.hello({ hello: "tests" }); - t.is(result, "tests"); -}); +test('hello', async t => { + const { result } = await contract.hello({ hello: 'tests' }) + t.is(result, 'tests') +}) -test("woid", async (t) => { - t.is((await contract.woid()).result, null); -}); +test('woid', async t => { + t.is((await contract.woid()).result, null) +}) -test("u32_fail_on_even", async (t) => { +test('u32_fail_on_even', async t => { t.deepEqual( (await contract.u32_fail_on_even({ u32_: 1 })).result, - new ContractClient.Ok(1), - ); + new ContractClient.Ok(1) + ) t.deepEqual( (await contract.u32_fail_on_even({ u32_: 0 })).result, - new ContractClient.Err({ message: "Please provide an odd number" }), - ); -}); + new ContractClient.Err({ message: "Please provide an odd number" }) + ) +}) -test("u32_", async (t) => { - t.is((await contract.u32_({ u32_: 1 })).result, 1); -}); +test('u32_', async t => { + t.is((await contract.u32_({ u32_: 1 })).result, 1) +}) -test("i32_", async (t) => { - t.is((await contract.i32_({ i32_: 1 })).result, 1); -}); +test('i32_', async t => { + t.is((await contract.i32_({ i32_: 1 })).result, 1) +}) -test("i64_", async (t) => { - t.is((await contract.i64_({ i64_: 1n })).result, 1n); -}); +test('i64_', async t => { + t.is((await contract.i64_({ i64_: 1n })).result, 1n) +}) test("strukt_hel", async (t) => { - const test = { a: 0, b: true, c: "world" }; - t.deepEqual((await contract.strukt_hel({ strukt: test })).result, [ - "Hello", - "world", - ]); -}); + const test = { a: 0, b: true, c: "world" } + t.deepEqual((await contract.strukt_hel({ strukt: test })).result, ["Hello", "world"]) +}) test("strukt", async (t) => { - const test = { a: 0, b: true, c: "hello" }; - t.deepEqual((await contract.strukt({ strukt: test })).result, test); -}); - -test("simple first", async (t) => { - const arg = { tag: "First", values: undefined } as const; - const ret = { tag: "First" }; - t.deepEqual((await contract.simple({ simple: arg })).result, ret); -}); - -test("simple second", async (t) => { - const arg = { tag: "Second", values: undefined } as const; - const ret = { tag: "Second" }; - t.deepEqual((await contract.simple({ simple: arg })).result, ret); -}); - -test("simple third", async (t) => { - const arg = { tag: "Third", values: undefined } as const; - const ret = { tag: "Third" }; - t.deepEqual((await contract.simple({ simple: arg })).result, ret); -}); - -test("complex with struct", async (t) => { - const arg = { - tag: "Struct", - values: [{ a: 0, b: true, c: "hello" }], - } as const; - const ret = { tag: "Struct", values: [{ a: 0, b: true, c: "hello" }] }; - t.deepEqual((await contract.complex({ complex: arg })).result, ret); -}); - -test("complex with tuple", async (t) => { - const arg = { - tag: "Tuple", - values: [ - [ - { a: 0, b: true, c: "hello" }, - { tag: "First", values: undefined }, - ], - ], - } as const; - const ret = { - tag: "Tuple", - values: [[{ a: 0, b: true, c: "hello" }, { tag: "First" }]], - }; - t.deepEqual((await contract.complex({ complex: arg })).result, ret); -}); - -test("complex with enum", async (t) => { - const arg = { - tag: "Enum", - values: [{ tag: "First", values: undefined }], - } as const; - const ret = { tag: "Enum", values: [{ tag: "First" }] }; - t.deepEqual((await contract.complex({ complex: arg })).result, ret); -}); - -test("complex with asset", async (t) => { - const arg = { tag: "Asset", values: [publicKey, 1n] } as const; - const ret = { tag: "Asset", values: [publicKey, 1n] }; - t.deepEqual((await contract.complex({ complex: arg })).result, ret); -}); - -test("complex with void", async (t) => { - const arg = { tag: "Void", values: undefined } as const; - const ret = { tag: "Void" }; - t.deepEqual((await contract.complex({ complex: arg })).result, ret); -}); - -test("addresse", async (t) => { - t.deepEqual( - (await contract.addresse({ addresse: publicKey })).result, - publicKey, - ); -}); - -test("bytes", async (t) => { - const bytes = Buffer.from("hello"); - t.deepEqual((await contract.bytes({ bytes })).result, bytes); -}); - -test("bytes_n", async (t) => { - const bytes_n = Buffer.from("123456789"); // what's the correct way to construct bytes_n? - t.deepEqual((await contract.bytes_n({ bytes_n })).result, bytes_n); -}); - -test("card", async (t) => { - const card = 11; - t.is((await contract.card({ card })).result, card); -}); - -test("boolean", async (t) => { - t.is((await contract.boolean({ boolean: true })).result, true); -}); - -test("not", async (t) => { - t.is((await contract.not({ boolean: true })).result, false); -}); - -test("i128", async (t) => { - t.is((await contract.i128({ i128: -1n })).result, -1n); -}); - -test("u128", async (t) => { - t.is((await contract.u128({ u128: 1n })).result, 1n); -}); - -test("multi_args", async (t) => { - t.is((await contract.multi_args({ a: 1, b: true })).result, 1); - t.is((await contract.multi_args({ a: 1, b: false })).result, 0); -}); - -test("map", async (t) => { - const map = new Map(); - map.set(1, true); - map.set(2, false); + const test = { a: 0, b: true, c: "hello" } + t.deepEqual((await contract.strukt({ strukt: test })).result, test) +}) + +test('simple first', async t => { + const arg = { tag: 'First', values: undefined } as const + const ret = { tag: 'First' } + t.deepEqual((await contract.simple({ simple: arg })).result, ret) +}) + +test('simple second', async t => { + const arg = { tag: 'Second', values: undefined } as const + const ret = { tag: 'Second' } + t.deepEqual((await contract.simple({ simple: arg })).result, ret) +}) + +test('simple third', async t => { + const arg = { tag: 'Third', values: undefined } as const + const ret = { tag: 'Third' } + t.deepEqual((await contract.simple({ simple: arg })).result, ret) +}) + +test('complex with struct', async t => { + const arg = { tag: 'Struct', values: [{ a: 0, b: true, c: 'hello' }] } as const + const ret = { tag: 'Struct', values: [{ a: 0, b: true, c: 'hello' }] } + t.deepEqual((await contract.complex({ complex: arg })).result, ret) +}) + +test('complex with tuple', async t => { + const arg = { tag: 'Tuple', values: [[{ a: 0, b: true, c: 'hello' }, { tag: 'First', values: undefined }]] } as const + const ret = { tag: 'Tuple', values: [[{ a: 0, b: true, c: 'hello' }, { tag: 'First' }]] } + t.deepEqual((await contract.complex({ complex: arg })).result, ret) +}) + +test('complex with enum', async t => { + const arg = { tag: 'Enum', values: [{ tag: 'First', values: undefined }] } as const + const ret = { tag: 'Enum', values: [{ tag: 'First' }] } + t.deepEqual((await contract.complex({ complex: arg })).result, ret) +}) + +test('complex with asset', async t => { + const arg = { tag: 'Asset', values: [publicKey, 1n] } as const + const ret = { tag: 'Asset', values: [publicKey, 1n] } + t.deepEqual((await contract.complex({ complex: arg })).result, ret) +}) + +test('complex with void', async t => { + const arg = { tag: 'Void', values: undefined } as const + const ret = { tag: 'Void' } + t.deepEqual((await contract.complex({ complex: arg })).result, ret) +}) + +test('addresse', async t => { + t.deepEqual((await contract.addresse({ addresse: publicKey })).result, publicKey) +}) + +test('bytes', async t => { + const bytes = Buffer.from('hello') + t.deepEqual((await contract.bytes({ bytes })).result, bytes) +}) + +test('bytes_n', async t => { + const bytes_n = Buffer.from('123456789') // what's the correct way to construct bytes_n? + t.deepEqual((await contract.bytes_n({ bytes_n })).result, bytes_n) +}) + +test('card', async t => { + const card = 11 + t.is((await contract.card({ card })).result, card) +}) + +test('boolean', async t => { + t.is((await contract.boolean({ boolean: true })).result, true) +}) + +test('not', async t => { + t.is((await contract.not({ boolean: true })).result, false) +}) + +test('i128', async t => { + t.is((await contract.i128({ i128: -1n })).result, -1n) +}) + +test('u128', async t => { + t.is((await contract.u128({ u128: 1n })).result, 1n) +}) + +test('multi_args', async t => { + t.is((await contract.multi_args({ a: 1, b: true })).result, 1) + t.is((await contract.multi_args({ a: 1, b: false })).result, 0) +}) + +test('map', async t => { + const map = new Map() + map.set(1, true) + map.set(2, false) // map.set(3, 'hahaha') // should throw an error - const ret = Array.from(map.entries()); - t.deepEqual((await contract.map({ map })).result, ret); -}); + const ret = Array.from(map.entries()) + t.deepEqual((await contract.map({ map })).result, ret) +}) -test("vec", async (t) => { - const vec = [1, 2, 3]; - t.deepEqual((await contract.vec({ vec })).result, vec); -}); +test('vec', async t => { + const vec = [1, 2, 3] + t.deepEqual((await contract.vec({ vec })).result, vec) +}) -test("tuple", async (t) => { - const tuple = ["hello", 1] as const; - t.deepEqual((await contract.tuple({ tuple })).result, tuple); -}); +test('tuple', async t => { + const tuple = ['hello', 1] as const + t.deepEqual((await contract.tuple({ tuple })).result, tuple) +}) -test("option", async (t) => { - t.deepEqual((await contract.option({ option: 1 })).result, 1); +test('option', async t => { + // this makes sense + t.deepEqual((await contract.option({ option: 1 })).result, 1) - t.deepEqual((await contract.option({ option: undefined })).result, null); + // this passes but shouldn't + t.deepEqual((await contract.option({ option: undefined })).result, undefined) // this is the behavior we probably want, but fails // t.deepEqual(await contract.option(), undefined) // typing and implementation require the object // t.deepEqual((await contract.option({})).result, undefined) // typing requires argument; implementation would be fine with this // t.deepEqual((await contract.option({ option: undefined })).result, undefined) -}); - -test("u256", async (t) => { - t.is((await contract.u256({ u256: 1n })).result, 1n); -}); +}) -test("i256", async (t) => { - t.is((await contract.i256({ i256: -1n })).result, -1n); -}); +test('u256', async t => { + t.is((await contract.u256({ u256: 1n })).result, 1n) +}) -test("string", async (t) => { - t.is((await contract.string({ string: "hello" })).result, "hello"); -}); +test('i256', async t => { + t.is((await contract.i256({ i256: -1n })).result, -1n) +}) -test("tuple_strukt", async (t) => { - const arg = [ - { a: 0, b: true, c: "hello" }, - { tag: "First", values: undefined }, - ] as const; - const res = [{ a: 0, b: true, c: "hello" }, { tag: "First" }]; - t.deepEqual((await contract.tuple_strukt({ tuple_strukt: arg })).result, res); -}); +test('string', async t => { + t.is((await contract.string({ string: 'hello' })).result, 'hello') +}) -test("timepoint", async (t) => { - t.is((await contract.timepoint({ timepoint: 1n })).result, 1n); -}); - -test("duration", async (t) => { - t.is((await contract.duration({ duration: 1n })).result, 1n); -}); +test('tuple_strukt', async t => { + const arg = [{ a: 0, b: true, c: 'hello' }, { tag: 'First', values: undefined }] as const + const res = [{ a: 0, b: true, c: 'hello' }, { tag: 'First' }] + t.deepEqual((await contract.tuple_strukt({ tuple_strukt: arg })).result, res) +}) From 72458faedfdef109f0b52eface1a74e14886bc30 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 6 May 2026 03:15:41 +0000 Subject: [PATCH 4/5] emit deprecated standalone alias for local --- .../soroban-spec-typescript/src/boilerplate.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index c717317df6..890b49140f 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -128,6 +128,21 @@ impl Project { NETWORK_PASSPHRASE_LOCAL => "local", _ => "unknown", }; + if network_passphrase == NETWORK_PASSPHRASE_LOCAL { + return format!( + r#"export const networks = {{ + local: {{ + networkPassphrase: "{network_passphrase}", + contractId: "{contract_id}", + }}, + /** @deprecated Use `local` instead. */ + standalone: {{ + networkPassphrase: "{network_passphrase}", + contractId: "{contract_id}", + }}, +}} as const"# + ); + } format!( r#"export const networks = {{ {network}: {{ From 7113dbb0cd4ecfac32e7057c2cf7b72f3b8426ca Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 6 May 2026 03:17:12 +0000 Subject: [PATCH 5/5] drop unreachable local match arm --- cmd/crates/soroban-spec-typescript/src/boilerplate.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index 890b49140f..2b19982f45 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -122,12 +122,6 @@ impl Project { } let contract_id = contract_id.unwrap(); let network_passphrase = network_passphrase.unwrap(); - let network = match network_passphrase { - NETWORK_PASSPHRASE_TESTNET => "testnet", - NETWORK_PASSPHRASE_FUTURENET => "futurenet", - NETWORK_PASSPHRASE_LOCAL => "local", - _ => "unknown", - }; if network_passphrase == NETWORK_PASSPHRASE_LOCAL { return format!( r#"export const networks = {{ @@ -143,6 +137,11 @@ impl Project { }} as const"# ); } + let network = match network_passphrase { + NETWORK_PASSPHRASE_TESTNET => "testnet", + NETWORK_PASSPHRASE_FUTURENET => "futurenet", + _ => "unknown", + }; format!( r#"export const networks = {{ {network}: {{