Skip to content

Commit

Permalink
Add a ContractClient libraryy for easy contract interaction (#929)
Browse files Browse the repository at this point in the history
* Add generation of contract clients and an `AssembledTransaction` abstraction (#891)
- new e2e tests copied from cli `ts-tests` for the generated bindings, but
  with TypeScript removed because the ContractClient is generated here
  dynamically at run time, so we cannot know the types at compile time in
  the tests.
- generate JSON specs from local .wasm files during initiaze.sh instead
  of generating TS bindings. As explained in the new wasms/specs/README,
  this is a bummer, but is temporary
* Update soroban-cli and sync with upstream `master` (#911)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: George <Shaptic@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Make simulation optional, simplify wallet/signer interface (#921)

* Update examples to use new module and package structure. (#900)

* Fixup deprecation to specify exact version
* Upgrade references to use latest modules

* Bump follow-redirects from 1.15.3 to 1.15.4 (#906)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](follow-redirects/follow-redirects@v1.15.3...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Export the individual event response instance (#904)

* Add support for new `sendTransaction` response field (#905)

* Add checks to ensure incorrect fields don't sneak in

* Update README to flow better (#907)

* Prepare v11.2.0 for release (#908)

* Upgrade all dependencies besides chai
* Add changelog entries

* Eliminating `utility-types` dependency entirely (#912)

Eliminated the 'utility-types' package since its functionalities are likely
replaced by native TypeScript features. This change includes cleaning up imports
and references in the codebase and updating the package.json and yarn.lock
accordingly, resulting in a leaner dependency graph and potentially reducing
installation times and package size.

Co-authored-by: Sérgio Luis <sergiocl@airtm.io>

* Release v11.2.1 (#913)

* Upgrade dependencies and stellar-base

* fix: stop using TimeoutInfinite

* optional simulate & wallet, editable TransactionBuilder

- Can now pass an `account` OR `wallet` when constructing the
  ContractClient, or none! If you pass none, you can still make view
  calls, since they don't need a signer. You will need to pass a
  `wallet` when calling things that need it, like `signAndSend`.

- You can now pass `simulate: false` when first creating your
  transaction to skip simulation. You can then modify the transaction
  using the TransactionBuilder at `tx.raw` before manually calling
  `simulate`. Example:

      const tx = await myContract.myMethod(
        { args: 'for', my: 'method', ... },
        { simulate: false }
      );
      tx.raw.addMemo(Memo.text('Nice memo, friend!'))
      await tx.simulate();

- Error types are now collected under `AssembledTransaction.Errors` and
  `SentTransaction.Errors`.

* Ensure that event streaming tests write a valid stream (#917)
* Release v11.2.2 (#918)
* export ExampleNodeWallet from lib

Tyler van der Hoeven thought this would be useful.

The current place it's exported from is surpassingly silly. But it
functions properly and the tests fail the same way they failed before.

* Drop all usage of array-based passing (#924)

* feat(e2e-tests): new account & contract per test

- New `clientFor` that instantiates a ContractClient for given
  contract, as well as initializes a new account, funding it with
  friendbot
- Can also use `generateFundedKeypair` directly, as with test-swap
- Stop generating anything in initialize.sh. Just check that the network
  is running and the pinned binary is installed, and fund the
  `$SOROBAN_ACCOUNT`.

  Ideally we wouldn't use the binary at all, but for now the tests are
  still shelling out to the CLI, so it's worth keeping the pinning
  around

* wallet/signer only needs three methods

* feat: no more `Wallet` interface

Instead, just accept the things that Wallet contained.

This avoids the conundrum of what to call the thing.

- `Wallet` seems too high-level. Too high-level to be the concern of
  stellar-sdk, and too high-level for the thing being described here.
  It's really just two functions: `signTransaction` and `signAuthEntry`.
- No need for this thing to defined `getPublicKey`, let alone any of the
  more complicated wrappers around it that it used to. Just have people
  pass in a `publicKey`. For convenience' sake, I also allowed this to
  be a Promise of a string, so that you don't need to instantiate
  ContractClient asynchronously, instead doing something like:

      new ContractClient({
        publicKey: asyncPublicKeyLookupFromWallet(),
        ...
      })

  This helps when getting public keys in a browser environment, where
  public key lookup is async, and adds little complexity to the logic
  here.

* rm getAccount from exposed interface

* make simulation public; wrap comments

* explicit allowHttp

* test(ava): set timeout to 2m

* build: move ExampleNodeWallet to own entrypoint

No need to pollute the global API or bundle size with this.

* build: move ContractClient & AssembledTransaction

These are a bit higher-level and experimental, at this point, so let's
not clutter the global API or the bundle size unless people really want
it.

* fix: allow overriding 'publicKey' for 'signAuthEntries'

* feat(contract-client): require publicKey

* fix: use Networks from stellar-base

* doc: explain 'errorTypes' param

* build: ContractClient-related things in one dir

* typo

* move primitive type defs to contractclient

* rm ContractClient.generate; do it in constructor

* feat: separate rust_types to own import path

* feat: don't make people import and use Networks enum

I personally find TS enums a little surprising to work with, and my own
codebases already have network passphrases littered throughout. I think
we can upgrade to use the enum later, after more discussion about the
exact interface. Let's not tangle that up in this change.

* doc: include rust_types readme info in build

the README.md file is not included in the `lib/rust_types` built
version, so it's better to include it in a file that people can find by
using the go-to-definition function in their editor, such as a
`rust_types.ts` file directly, which gets built as
`lib/rust_types.d.ts`.

* build: make it easier to import rust_types

* feat: basicNodeSigner as a plain-object factory

Our suggested approach of spreading `signer` into `ContractClient`
constructors causes typing issues, since `networkPassphrase` is a
private field inside BasicNodeSigner. This means the `signer` needs to
be spread in before the inclusion of `networkPassphrase`, otherwise it
gets overwritten with `undefined` (or maybe TypeScript just thinks it
will get overwritten).

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: George <Shaptic@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sérgio Luis <sergiolclem@gmail.com>
Co-authored-by: Sérgio Luis <sergiocl@airtm.io>

* fix(contract-client): stop jsifying method names

This implementation needs to match what is done in the TS Bindings in
Rust. Keeping "JSification" logic consistent in both is not worth the
slight nicety of allowing people to type camelCaseMethodNames in JS.

Additionally, having camelCaseMethodNames in one context when the real
method name is probably_snake_case could lead to confusion. If someone
types a camelCaseName in their CLI, the CLI will complain, and they
might not know what's going on.

* docs(contract-client): clean api, write a book

Yes, a whole book about AssembledTransaction. It needed documentation;
why not make it useful.

This also removes an obsolute method, marks a couple as private,
adds detail to other comments, fixes the `fee` type, updates
SentTransaction docs, and organizes the code a bit.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: George <Shaptic@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sérgio Luis <sergiolclem@gmail.com>
Co-authored-by: Sérgio Luis <sergiocl@airtm.io>
  • Loading branch information
5 people committed Mar 20, 2024
1 parent 53ebe3e commit e66112d
Show file tree
Hide file tree
Showing 34 changed files with 3,361 additions and 959 deletions.
129 changes: 129 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# paths = ["/path/to/override"] # path dependency overrides

[alias] # command aliases
install_soroban = "install --version 20.2.0 --root ./target soroban-cli --debug"
# b = "build --target wasm32-unknown-unknown --release"
# c = "check"
# t = "test"
# r = "run"
# rr = "run --release"
# recursive_example = "rr --example recursions"
# space_example = ["run", "--release", "--", "\"command list\""]

[build]
# jobs = 1 # number of parallel jobs, defaults to # of CPUs
# rustc = "rustc" # the rust compiler tool
# rustc-wrapper = "…" # run this wrapper instead of `rustc`
# rustc-workspace-wrapper = "…" # run this wrapper instead of `rustc` for workspace members
# rustdoc = "rustdoc" # the doc generator tool
# target = "wasm32-unknown-unknown" # build for the target triple (ignored by `cargo install`)
# target-dir = "target" # path of where to place all generated artifacts
# rustdocflags = ["…", "…"] # custom flags to pass to rustdoc
# incremental = true # whether or not to enable incremental compilation
# dep-info-basedir = "…" # path for the base directory for targets in depfiles

# [doc]
# browser = "chromium" # browser to use with `cargo doc --open`,
# # overrides the `BROWSER` environment variable

# [env]
# # Set ENV_VAR_NAME=value for any process run by Cargo
# ENV_VAR_NAME = "value"
# # Set even if already present in environment
# ENV_VAR_NAME_2 = { value = "value", force = true }
# # Value is relative to .cargo directory containing `config.toml`, make absolute
# ENV_VAR_NAME_3 = { value = "relative/path", relative = true }

# [future-incompat-report]
# frequency = 'always' # when to display a notification about a future incompat report

# [cargo-new]
# vcs = "none" # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none')

# [http]
# debug = false # HTTP debugging
# proxy = "host:port" # HTTP proxy in libcurl format
# ssl-version = "tlsv1.3" # TLS version to use
# ssl-version.max = "tlsv1.3" # maximum TLS version
# ssl-version.min = "tlsv1.1" # minimum TLS version
# timeout = 30 # timeout for each HTTP request, in seconds
# low-speed-limit = 10 # network timeout threshold (bytes/sec)
# cainfo = "cert.pem" # path to Certificate Authority (CA) bundle
# check-revoke = true # check for SSL certificate revocation
# multiplexing = true # HTTP/2 multiplexing
# user-agent = "…" # the user-agent header

# [install]
# root = "/some/path" # `cargo install` destination directory

# [net]
# retry = 2 # network retries
# git-fetch-with-cli = true # use the `git` executable for git operations
# offline = true # do not access the network

# [net.ssh]
# known-hosts = ["..."] # known SSH host keys

# [patch.<registry>]
# # Same keys as for [patch] in Cargo.toml

# [profile.<name>] # Modify profile settings via config.
# inherits = "dev" # Inherits settings from [profile.dev].
# opt-level = 0 # Optimization level.
# debug = true # Include debug info.
# split-debuginfo = '...' # Debug info splitting behavior.
# debug-assertions = true # Enables debug assertions.
# overflow-checks = true # Enables runtime integer overflow checks.
# lto = false # Sets link-time optimization.
# panic = 'unwind' # The panic strategy.
# incremental = true # Incremental compilation.
# codegen-units = 16 # Number of code generation units.
# rpath = false # Sets the rpath linking option.
# [profile.<name>.build-override] # Overrides build-script settings.
# # Same keys for a normal profile.
# [profile.<name>.package.<name>] # Override profile for a package.
# # Same keys for a normal profile (minus `panic`, `lto`, and `rpath`).

# [registries.<name>] # registries other than crates.io
# index = "…" # URL of the registry index
# token = "…" # authentication token for the registry

# [registry]
# default = "…" # name of the default registry
# token = "…" # authentication token for crates.io

# [source.<name>] # source definition and replacement
# replace-with = "…" # replace this source with the given named source
# directory = "…" # path to a directory source
# registry = "…" # URL to a registry source
# local-registry = "…" # path to a local registry source
# git = "…" # URL of a git repository source
# branch = "…" # branch name for the git repository
# tag = "…" # tag name for the git repository
# rev = "…" # revision for the git repository

# [target.<triple>]
# linker = "…" # linker to use
# runner = "…" # wrapper to run executables
# rustflags = ["…", "…"] # custom flags for `rustc`

# [target.<cfg>]
# runner = "…" # wrapper to run executables
# rustflags = ["…", "…"] # custom flags for `rustc`

# [target.<triple>.<links>] # `links` build script override
# rustc-link-lib = ["foo"]
# rustc-link-search = ["/path/to/foo"]
# rustc-flags = ["-L", "/some/path"]
# rustc-cfg = ['key="value"']
# rustc-env = {key = "value"}
# rustc-cdylib-link-arg = ["…"]
# metadata_key1 = "value"
# metadata_key2 = "value"

# [term]
# quiet = false # whether cargo output is quiet
# verbose = false # whether cargo provides verbose output
# color = 'auto' # whether cargo colorizes output
# progress.when = 'auto' # whether cargo shows progress bar
# progress.width = 80 # width of progress bar
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SOROBAN_NETWORK_PASSPHRASE="Standalone Network ; February 2017"
SOROBAN_RPC_URL="http://localhost:8000/soroban/rpc"
SOROBAN_ACCOUNT="me"
FRIENDBOT_URL="http://localhost:8000/friendbot"
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib
39 changes: 39 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: ContractClient

on:
push:
branches: [master, release/**]
pull_request:

jobs:
test:
name: test generated ContractClient
runs-on: ubuntu-22.04
services:
rpc:
image: stellar/quickstart:soroban-dev@sha256:0ad51035cf7caba2fd99c7c1fad0945df6932be7d5c893e1520ccdef7d6a6ffe
ports:
- 8000:8000
env:
ENABLE_LOGS: true
NETWORK: local
ENABLE_SOROBAN_RPC: true
options: >-
--health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'"
--health-interval 10s
--health-timeout 5s
--health-retries 50
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

# Workaround for some `yarn` nonsense, see:
# https://github.com/yarnpkg/yarn/issues/6312#issuecomment-429685210
- run: yarn install --network-concurrency 1
- run: yarn build:prod
- run: yarn test:e2e

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ js-stellar-base/

test/unit/out/
.vscode/launch.json

target
.soroban
16 changes: 14 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@
"build:prod": "cross-env NODE_ENV=production yarn _build",
"build:node": "yarn _babel && yarn build:ts",
"build:ts": "tsc -p ./config/tsconfig.json",
"build:test": "tsc -p ./test/tsconfig.json",
"build:test": "tsc -p ./test/unit/tsconfig.json",
"build:browser": "webpack -c config/webpack.config.browser.js",
"build:docs": "cross-env NODE_ENV=docs yarn _babel",
"clean": "rm -rf lib/ dist/ coverage/ .nyc_output/ jsdoc/",
"clean": "rm -rf lib/ dist/ coverage/ .nyc_output/ jsdoc/ test/e2e/.soroban",
"docs": "yarn build:docs && jsdoc -c ./config/.jsdoc.json --verbose",
"test": "yarn build:test && yarn test:node && yarn test:integration && yarn test:browser",
"test:e2e": "./test/e2e/initialize.sh && ava",
"test:node": "yarn _nyc mocha --recursive 'test/unit/**/*.js'",
"test:integration": "yarn _nyc mocha --recursive 'test/integration/**/*.js'",
"test:browser": "karma start config/karma.conf.js",
Expand Down Expand Up @@ -97,6 +98,7 @@
"@types/sinon": "^17.0.2",
"@types/urijs": "^1.19.20",
"@typescript-eslint/parser": "^6.20.0",
"ava": "^5.3.1",
"axios-mock-adapter": "^1.22.0",
"babel-loader": "^9.1.3",
"babel-plugin-istanbul": "^6.1.1",
Expand All @@ -105,6 +107,7 @@
"chai-as-promised": "^7.1.1",
"chai-http": "^4.3.0",
"cross-env": "^7.0.3",
"dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.0.0",
Expand Down Expand Up @@ -150,5 +153,14 @@
"randombytes": "^2.1.0",
"toml": "^3.0.0",
"urijs": "^1.19.1"
},
"ava": {
"files": [
"./test/e2e/src/test-*"
],
"require": [
"dotenv/config"
],
"timeout": "2m"
}
}
Loading

0 comments on commit e66112d

Please sign in to comment.