Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Add TypeScript bindings #369

Merged
merged 20 commits into from
Aug 23, 2019
Merged

Add TypeScript bindings #369

merged 20 commits into from
Aug 23, 2019

Conversation

albrow
Copy link
Contributor

@albrow albrow commented Aug 21, 2019

Fixes #298.

This PR adds TypeScript bindings and an npm package for using Mesh in the browser. The Wasm bytecode is embedded in the package itself which makes it really easy to import and use. It also adds an example of how to import and use the TypeScript bindings.

Here's a breakdown of the directory structure and key files:

  • browser/ contains TypeScript bindings for running Mesh in the browser. This directory is a publishable npm package called @0x/mesh-browser.
    • go/ The source code for the Wasm bytecode that will be embedded in the package. It imports 0x-mesh/core and adds everything we need to the global scope.
    • scripts/ contains one-off scripts related to the TypeScript bindings.
      • generate_wasm_buffer.go a script that generates a TypeScript file containing the Wasm bytecode as a base64-encoded ArrayBuffer.
    • ts/ the entry point for the npm package. This is a lightweight wrapper around the variables that we injected into global scope that adds some extra niceties.
      • generated/ contains the TypeScript file generated by scripts/generate_wasm_buffer.go.
    • wasm/ contains the Wasm bytecode itself (the result of compiling go/main.go).
    • lib/ contains the JavaScript code, source maps, and type definitions (the result of compiling ts/).
  • examples/browser is an example of how to import and use the @0x/mesh-browser package in a browser-based application. It uses TypeScript and webpack.
    • src/ is the TypeScript code for the example application.
    • dist/ is where webpack outputs the results. Everything is compiled into a single bundle.js file.

I'm planning to clean this up and document it in a README, but for now here are the steps for running the example:

  1. In the browser/ directory run yarn install && yarn build.
  2. In the examples/browser directory run yarn install && yarn build.
  3. In the root of the repository, run goexec 'http.ListenAndServe(":8000", http.FileServer(http.Dir("./examples/browser/dist")))'
  4. Visit http://localhost:8000 in your browser and look at the console output.

@albrow
Copy link
Contributor Author

albrow commented Aug 22, 2019

Latest commit adds a setOrderEventsHandler method, which is analogous to the mesh_subscribe("orders") JSON RPC endpoint.

@albrow albrow force-pushed the feature/typescript-bindings branch from 733dee3 to 8aafd19 Compare August 22, 2019 20:30
@albrow albrow changed the title WIP: Add TypeScript bindings Add TypeScript bindings Aug 22, 2019
@albrow
Copy link
Contributor Author

albrow commented Aug 22, 2019

@fabioberger I removed the WIP tag and this PR is ready for review. I still expect that there will be some discussion about naming, interface design, and project structure.

browser/package.json Outdated Show resolved Hide resolved
browser/package.json Outdated Show resolved Hide resolved
const zeroExMesh: ZeroExMesh;
}

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabioberger We should probably generate docs for the TypeScript bindings similar to what we did for the TypeScript RPC client. Can you point me in the right direction? Alternatively we could do that in a separate PR since this is already pretty big.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need "@0x/ts-doc-gen": "^0.0.16", dep and a command:

"scripts": {
    "docs:md": "ts-doc-gen --sourceDir=./src --output=${npm_package_config_docsPath}"
},
"config": {
    "docsPath": "../../../docs/json_rpc_clients/typescript"
},

Just change the docsPath to where you want the MD generated to and it should work 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍@fabioberger just added this. Mind eyeballing the docs to make sure everything looks right?

@albrow
Copy link
Contributor Author

albrow commented Aug 22, 2019

I know there's not a lot of tests here. I'm planning to write integration tests in a separate PR. The way it will work is that we'll spin up a few nodes on a local network and confirm that they can connect and share orders with one another. It will involve coordinating between some native Go nodes and some that are running in a headless browser. In the meantime, examples/browser can serve as a sort of ad hoc integration test.

"webpack-cli": "^3.3.7"
},
"dependencies": {
"@0x/mesh-browser": "./../../browser/"
Copy link
Contributor Author

@albrow albrow Aug 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now the example uses a local copy of the TypeScript bindings. I'll update this to use the actual version once we have published the package on NPM.

loadEventName = "0xmeshload"
// orderEventsBufferSize is the buffer size for the orderEvents channel. If
// the buffer is full, any additional events won't be processed.
orderEventsBufferSize = 100
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to bump this up a bit higher?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Increasing orderEventsBufferSize reduces the chance of order events being missed but increases memory usage. I think 100 is a decent starting point but we can adjust it if needed. The channel should never get that full if an orderEventsHandler is set.

browser/go/main.go Outdated Show resolved Hide resolved
browser/package.json Outdated Show resolved Hide resolved
browser/package.json Outdated Show resolved Hide resolved
browser/package.json Outdated Show resolved Hide resolved
signedOrder: MeshSignedOrder;
kind: RejectedOrderKind;
status: RejectedOrderStatus;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all duplicated from @0x/mesh-rpc-client. Any ideas on how to avoid that? I can't think of any without creating a TS monorepo within this repo...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of anything else either. I'm not sure if it's worth the overhead of using a TS monorepo here. Let's copy it manually for now and discuss later?

browser/package.json Outdated Show resolved Hide resolved
return new Promise(resolve => setTimeout(resolve, ms));
}

function meshSignedOrderToSignedOrder(meshSignedOrder: MeshSignedOrder): SignedOrder {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you're calling MeshSignedOrder we call StringifiedSignedOrder in mesh-rpc-client. Thoughts on standardizing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... StringifiedSignedOrder is an okay name in this case because all the types are strings. However, I want to pick a name that highlights the pattern of converting between Go types and TypeScript types. I'm thinking that there will be other type conversions in the future and not just string to BigNumber. I can't think of a good name to cover the use cases in both mesh-rpc-client and mesh-browser. Maybe something like BasicSignedOrder?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My vote would perhaps be StringifiedSignedOrder for now, and if there are other types involved in the future, changing it then. Don't feel too strongly about this though, so we can also leave it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to go with WrapperSignedOrder, WrapperOrderEvent, WrapperValidationResults, etc. to more closely match the fact that these are types exposed by MeshWrapper that might need further conversion. This is what I was originally trying to show with the Mesh* prefix but I feel that name was too confusing. Happy to re-evaluate later.

examples/browser/src/index.ts Outdated Show resolved Hide resolved
examples/browser/src/index.ts Show resolved Hide resolved
albrow and others added 4 commits August 23, 2019 11:09
Co-Authored-By: Fabio B <me@fabioberger.com>
Co-Authored-By: Fabio B <me@fabioberger.com>
@albrow albrow merged commit 3e68040 into development Aug 23, 2019
@albrow albrow deleted the feature/typescript-bindings branch August 23, 2019 22:56
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement TypeScript/JavaScript bindings for interacting with Mesh from the browser
2 participants