Skip to content

Commit

Permalink
feat!: new exports ContractClient and Rpc
Browse files Browse the repository at this point in the history
- `SorobanRpc` now also exported as `Rpc`
- New main export `ContractClient`
- `ContractSpec` now available at `ContractClient.Spec`
- Also includes other supporting classes, functions, and types:
  - `ContractClient.AssembledTransaction`
  - `ContractClient.ClientOptions`
  - etc

These are also (maybe) available at top-level named export, if your
tooling supports the `exports` declaration:

    import { ClientOptions, AssembledTransaction } from 'stellar-sdk/Contract'
  • Loading branch information
chadoh committed May 14, 2024
1 parent 2ee6126 commit 798b4b6
Show file tree
Hide file tree
Showing 39 changed files with 160 additions and 93 deletions.
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,64 @@ A breaking change will get clearly marked in this log.

## Unreleased

### Breaking Changes

- `ContractClient` functionality previously added in [v11.3.0](https://github.com/stellar/js-stellar-sdk/releases/tag/v11.3.0) was exported in a non-standard way. You can now import it as any other stellar-sdk module.

```diff
- import { ContractClient } from '@stellar/stellar-sdk/lib/contract_client'
- import { ContractClient } from '@stellar/stellar-sdk'
```

Note that this top-level export is now a container for all ContractClient-related functionality. The ContractClient class is now available at `ContractClient.Client`.

Additionally, it is available from the `/ContractClient` entrypoint, if your version of Node ([and TypeScript!](https://stackoverflow.com/a/70020984/249801)) supports [the `exports` declaration](https://nodejs.org/api/packages.html#exports). Finally, some of its exports have been renamed.

```diff
import {
- ContractClient,
+ Client,
AssembledTransaction,
- ContractClientOptions,
+ Options,
SentTransaction,
-} from '@stellar/stellar-sdk/lib/contract_client'
+} from '@stellar/stellar-sdk/ContractClient'
```


- `ContractSpec` class now nested under `ContractClient` module, and has been renamed to `Spec`.

```diff
-import { ContractSpec } from '@stellar/stellar-sdk'
+import { ContractClient } from '@stellar/stellar-sdk'
+const { Spec } = ContractClient
```

Alternatively, you can import this from the `ContractClient` entrypoint.

```diff
-import { ContractSpec } from '@stellar/stellar-sdk'
+import { Spec } from '@stellar/stellar-sdk/ContractClient'
```

### Added

- `SorobanRpc` module is now also exported as `Rpc`. You can import it with either name.

```diff
import { SorobanRpc } from '@stellar/stellar-sdk'
+// OR
+import { Rpc } from '@stellar/stellar-sdk'
```

You can also now import its exports at the `/Rpc` entrypoint, if your version of Node ([and TypeScript!](https://stackoverflow.com/a/70020984/249801)) supports [the `exports` declaration](https://nodejs.org/api/packages.html#exports).

```diff
-import { SorobanRpc } from '@stellar/stellar-sdk'
-const { Api } = SorobanRpc
+import { Api } from '@stellar/stellar-sdk/Rpc'
```

## [v12.0.0-rc.2](https://github.com/stellar/js-stellar-sdk/compare/v11.3.0...v12.0.0-rc.2)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ The usage documentation for this library lives in a handful of places:
You can also refer to:

* the [documentation](https://developers.stellar.org/network/horizon) for the Horizon REST API (if using the `Horizon` module) and
* the [documentation](https://soroban.stellar.org/docs/reference/rpc) for Soroban RPC's API (if using the `SorobanRpc` module)
* the [documentation](https://soroban.stellar.org/docs/reference/rpc) for Soroban RPC's API (if using the `Rpc` module)

### Usage with React-Native

Expand Down
17 changes: 16 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@
"/lib",
"/dist"
],
"exports": {
".": {
"browser": "./dist/stellar-sdk.min.js",
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./ContractClient": {
"types": "./lib/contract_client/index.d.ts",
"default": "./lib/contract_client/index.js"
},
"./Rpc": {
"types": "./lib/rpc/index.d.ts",
"default": "./lib/rpc/index.js"
}
},
"scripts": {
"build": "cross-env NODE_ENV=development yarn _build",
"build:prod": "cross-env NODE_ENV=production yarn _build",
Expand Down Expand Up @@ -164,4 +179,4 @@
],
"timeout": "2m"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import {
} from "@stellar/stellar-base";
import type {
AssembledTransactionOptions,
ContractClientOptions,
Options,
MethodOptions,
Tx,
XDR_BASE64,
} from "./types";
import { Server } from "../server";
import { Api } from "../api";
import { assembleTransaction } from "../transaction";
import type { ContractClient } from "./client";
import { Server } from "../rpc/server";
import { Api } from "../rpc/api";
import { assembleTransaction } from "../rpc/transaction";
import type { Client } from "./client";
import { Err } from "./rust_result";
import {
DEFAULT_TIMEOUT,
Expand All @@ -33,7 +33,7 @@ export const NULL_ACCOUNT =
"GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";

/**
* The main workhorse of {@link ContractClient}. This class is used to wrap a
* The main workhorse of {@link Client}. This class is used to wrap a
* transaction-under-construction and provide high-level interfaces to the most
* common workflows, while still providing access to low-level stellar-sdk
* transaction manipulation.
Expand Down Expand Up @@ -70,7 +70,7 @@ export const NULL_ACCOUNT =
* ```
*
* While that looks pretty complicated, most of the time you will use this in
* conjunction with {@link ContractClient}, which simplifies it to:
* conjunction with {@link Client}, which simplifies it to:
*
* ```ts
* const { result } = await client.myReadMethod({
Expand All @@ -94,7 +94,7 @@ export const NULL_ACCOUNT =
* const sentTx = await assembledTx.signAndSend()
* ```
*
* Here we're assuming that you're using a {@link ContractClient}, rather than
* Here we're assuming that you're using a {@link Client}, rather than
* constructing `AssembledTransaction`'s directly.
*
* Note that `sentTx`, the return value of `signAndSend`, is a
Expand All @@ -118,7 +118,7 @@ export const NULL_ACCOUNT =
*
* If you need more control over the transaction before simulating it, you can
* set various {@link MethodOptions} when constructing your
* `AssembledTransaction`. With a {@link ContractClient}, this is passed as a
* `AssembledTransaction`. With a {@link Client}, this is passed as a
* second object after the arguments (or the only object, if the method takes
* no arguments):
*
Expand Down Expand Up @@ -521,7 +521,7 @@ export class AssembledTransaction<T> {
/**
* TSDoc: You must provide this here if you did not provide one before
*/
signTransaction?: ContractClientOptions["signTransaction"];
signTransaction?: Options["signTransaction"];
} = {}): Promise<SentTransaction<T>> => {
if (!this.built) {
throw new Error("Transaction has not yet been simulated");
Expand Down Expand Up @@ -669,7 +669,7 @@ export class AssembledTransaction<T> {
* the `signAuthEntry` function from the `ContractClient` options. Must
* sign things as the given `publicKey`.
*/
signAuthEntry?: ContractClientOptions["signAuthEntry"];
signAuthEntry?: Options["signAuthEntry"];
} = {}): Promise<void> => {
if (!this.built)
throw new Error("Transaction has not yet been assembled or simulated");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Keypair, TransactionBuilder, hash } from "@stellar/stellar-base";
import type { AssembledTransaction } from "./assembled_transaction";
import type { ContractClient } from "./client";
import type { Client } from "./client";

/**
* For use with {@link ContractClient} and {@link AssembledTransaction}.
* For use with {@link Client} and {@link AssembledTransaction}.
* Implements `signTransaction` and `signAuthEntry` with signatures expected by
* those classes. This is useful for testing and maybe some simple Node
* applications. Feel free to use this as a starting point for your own
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { xdr } from "@stellar/stellar-base";
import { ContractSpec } from "../../contract_spec";
import { Spec } from "./spec";
import { AssembledTransaction } from "./assembled_transaction";
import type { ContractClientOptions, MethodOptions } from "./types";
import type { Options, MethodOptions } from "./types";

export class ContractClient {
export class Client {
/**
* Generate a class from the contract spec that where each contract method
* gets included with an identical name.
Expand All @@ -13,10 +13,10 @@ export class ContractClient {
* transaction.
*/
constructor(
/** {@link ContractSpec} to construct a Client for */
public readonly spec: ContractSpec,
/** see {@link ContractClientOptions} */
public readonly options: ContractClientOptions,
/** {@link Spec} to construct a Client for */
public readonly spec: Spec,
/** see {@link Options} */
public readonly options: Options,
) {
this.spec.funcs().forEach((xdrFn) => {
const method = xdrFn.name().toString();
Expand All @@ -34,7 +34,7 @@ export class ContractClient {
...acc,
[curr.value()]: { message: curr.doc().toString() },
}),
{} as Pick<ContractClientOptions, "errorTypes">,
{} as Pick<Options, "errorTypes">,
),
parseResultXdr: (result: xdr.ScVal) =>
spec.funcResToNative(method, result),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ export * from "./basic_node_signer";
export * from "./client";
export * from "./rust_result";
export * from "./sent_transaction";
export * from "./spec";
export * from "./types";
export * from "./utils";
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* disable max-classes rule, because extending error shouldn't count! */
/* eslint max-classes-per-file: 0 */
import { SorobanDataBuilder, TransactionBuilder } from "@stellar/stellar-base";
import type { ContractClientOptions, MethodOptions, Tx } from "./types";
import { Server } from "../server"
import { Api } from "../api"
import type { Options, MethodOptions, Tx } from "./types";
import { Server } from "../rpc/server"
import { Api } from "../rpc/api"
import { DEFAULT_TIMEOUT, withExponentialBackoff } from "./utils";
import type { AssembledTransaction } from "./assembled_transaction";

Expand Down Expand Up @@ -53,7 +53,7 @@ export class SentTransaction<T> {
};

constructor(
public signTransaction: ContractClientOptions["signTransaction"],
public signTransaction: Options["signTransaction"],
public assembled: AssembledTransaction<T>,
) {
if (!signTransaction) {
Expand All @@ -73,7 +73,7 @@ export class SentTransaction<T> {
*/
static init = async <U>(
/** More info in {@link MethodOptions} */
signTransaction: ContractClientOptions["signTransaction"],
signTransaction: Options["signTransaction"],
/** {@link AssembledTransaction} from which this SentTransaction was initialized */
assembled: AssembledTransaction<U>,
): Promise<SentTransaction<U>> => {
Expand Down
4 changes: 2 additions & 2 deletions src/contract_spec.ts → src/contract_client/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Contract,
scValToBigInt,
} from "@stellar/stellar-base"
import { Ok } from "./soroban/contract_client/rust_result"
import { Ok } from "./rust_result"

export interface Union<T> {
tag: string;
Expand Down Expand Up @@ -48,7 +48,7 @@ function readObj(args: object, input: xdr.ScSpecFunctionInputV0): any {
* console.log(result); // {success: true}
* ```
*/
export class ContractSpec {
export class Spec {
public entries: xdr.ScSpecEntry[] = [];

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* disable PascalCase naming convention, to avoid breaking change */
/* eslint-disable @typescript-eslint/naming-convention */
import { BASE_FEE, Memo, MemoType, Operation, Transaction, xdr } from "@stellar/stellar-base";
import type { ContractClient } from "./client";
import type { Client } from "./client";
import type { AssembledTransaction } from "./assembled_transaction";
import { DEFAULT_TIMEOUT } from "./utils";

Expand All @@ -23,7 +23,7 @@ export type Duration = bigint;
*/
export type Tx = Transaction<Memo<MemoType>, Operation[]>;

export type ContractClientOptions = {
export type Options = {
/**
* The public key of the account that will send this transaction. You can
* override this for specific methods later, like
Expand Down Expand Up @@ -74,14 +74,14 @@ export type ContractClientOptions = {
allowHttp?: boolean;
/**
* This gets filled in automatically from the ContractSpec when you
* instantiate a {@link ContractClient}.
* instantiate a {@link Client}.
*
* Background: If the contract you're calling uses the `#[contracterror]`
* macro to create an `Error` enum, then those errors get included in the
* on-chain XDR that also describes your contract's methods. Each error will
* have a specific number.
*
* A ContractClient makes method calls with an {@link AssembledTransaction}.
* A Client makes method calls with an {@link AssembledTransaction}.
* When one of these method calls encounters an error, `AssembledTransaction`
* will first attempt to parse the error as an "official" `contracterror`
* error, by using this passed-in `errorTypes` object. See
Expand Down Expand Up @@ -112,7 +112,7 @@ export type MethodOptions = {
};

export type AssembledTransactionOptions<T = string> = MethodOptions &
ContractClientOptions & {
Options & {
method: string;
args?: any[];
parseResultXdr: (xdr: xdr.ScVal) => T;
Expand Down
File renamed without changes.
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ export * as Friendbot from './friendbot';
export * as Horizon from './horizon';

// Soroban RPC-related classes to expose
export * as SorobanRpc from './soroban';
export * from './contract_spec';
export * as Rpc from './rpc';
export * as SorobanRpc from './rpc';

// Soroban Contract-related classes to expose
export * as ContractClient from './contract_client'

// expose classes and functions from stellar-base
export * from '@stellar/stellar-base';
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion src/soroban/index.ts → src/rpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ export { Server, Durability } from "./server";
export { default as AxiosClient } from "./axios";
export { parseRawSimulation, parseRawEvents } from "./parsers";
export * from "./transaction";
export * as ContractClient from "./contract_client";

export default module.exports;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 3 additions & 5 deletions test/e2e/src/test-custom-types.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
const test = require('ava')
const { Address, SorobanRpc } = require('../../..')
const { Address, ContractClient } = require('../../..')
const { clientFor } = require('./util')

const { Ok, Err } = SorobanRpc.ContractClient

test.before(async t => {
const { client, keypair, contractId } = await clientFor('customTypes')
const publicKey = keypair.publicKey()
Expand Down Expand Up @@ -31,11 +29,11 @@ test('woid', async t => {
test('u32_fail_on_even', async t => {
t.deepEqual(
(await t.context.client.u32_fail_on_even({ u32_: 1 })).result,
new Ok(1)
new ContractClient.Ok(1)
)
t.deepEqual(
(await t.context.client.u32_fail_on_even({ u32_: 2 })).result,
new Err({ message: "Please provide an odd number" })
new ContractClient.Err({ message: "Please provide an odd number" })
)
})

Expand Down
Loading

0 comments on commit 798b4b6

Please sign in to comment.