Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaces custom VM with custom "Urbit" element #26

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions templates/frontend/components/bos.config.json

This file was deleted.

1 change: 0 additions & 1 deletion templates/frontend/components/widget/app.jsx

This file was deleted.

152 changes: 84 additions & 68 deletions templates/frontend/gateway/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
This is a [React](https://reactjs.org/) app bootstrapped with [`bos-workspace` component testing environment](https://github.com/urbit/bos-workspace) and [Urbit-aware NEAR Social VM](https://github.com/urbit/NearSocialVM).
—> [near-bos-webcomponent](https://github.com/nearbuilders/near-bos-webcomponent) with [Urbit HTTP API](https://developers.urbit.org/guides/additional/http-api-guide) installed, in order to provide a sandbox for builders wanting to create decentralized Urbit apps on BOS.

## Prerequisites

- Make sure you have a [current version of Node.js](https://nodejs.org) installed – we are targeting versions `18` for frontend/gateways.
- Have [Urbit environment setup](https://docs.urbit.org/courses/environment#creating-a-fake-ship) and running Urbit "fakeship".

> We strongly recommend you to follow our [creating your first Urbit-compatible NEAR BOS gateway](https://docs.urbit.org/) if you are new to Urbit or isn’t so familiar with BOS.
> We strongly recommend you to follow our [creating your first Urbit-compatible NEAR BOS gateway](https://docs.urbit.org/) if you are new to Urbit or aren't so familiar with BOS.

## Getting Started
## Getting started

First, run the development server:
To run locally, install packages using `yarn` or `pnpm`:

```
pnpm start
```bash
pnpm install
```

Open [http://localhost:8081](http://localhost:8081) with your browser to see the result.
Then, run the dev command:

This gateway is an ideal environment to develop Urbit-aware components to deploy on the NEAR blockchain, or develop an entire Urbit aware BOS gateway.
```bash
pnpm run dev
```

Build local components run
This will start a local [bos-workspace](https://github.com/nearbuilders/bos-workspace) dev server to build and serve your local widgets via RPC proxy with hot reload, and watch for changes to the gateway (React dApp) itself.

```
pnpm run component-build
#or
pnpm start
```
If the gateway does not automatically open, go to [http://localhost:8081](http://localhost:8081) with your browser to see the result.

To connect BOS gateway to your Urbit fakeship
specify credentials in `.env` file.
## Connecting to Urbit

To connect a BOS gateway to your Urbit fakeship,
specify the credentials in `.env` file.

```.env
# fakeship name without ~
Expand All @@ -41,102 +41,95 @@ REACT_APP_HOST=http://localhost:8080
REACT_APP_CODE=lidlut-tabwed-pillex-ridrup
```

Get fakeship access key, run +code command in your fakeship’s dojo (Urbit's command-line application).
Get the fakeship access key by running the `+code` command in your fakeship’s dojo (Urbit's command-line application).

```
```cmd
> +code
lidlut-tabwed-pillex-ridrup
```

### Gateway structure
## Project Structure

`/src` - React dApp, gateway itself.
`/src` - React dApp, "gateway" connected to the [Urbit-aware NEAR Social VM](https://github.com/urbit/NearSocialVM) -- it is prepared as a web component, originally derived from [near-bos-webcomponent](https://github.com/nearbuilders/near-bos-webcomponent).

`/apps` - a bos-workspace testing environment for your components.
`/widget` - bos-workspace directory to hold [`Widget`](https://docs.near.org/build/near-components/what-is) code ([NEAR components](https://docs.near.org/build/near-components/what-is)). The contents of this directory are built and served, and are automatically hooked up to the gateway via a proxy RPC. They will be deployed to the social.near and will be accessible via `src`, e.g. "urbitlabs.near/widget/app".

### Importing NEAR components

To import local or onchain components into your React dApp `/src` we will use predefined component called `Widget`.

```
```javascript
import { Widget } from 'near-social-vm'
```

If you’re testing local components, you’ll need to import them from `/build/data.json`.

```
import localComponents from '/../build/data.json'

const Header = localComponents['account.Urbit/widget/components.header']

function Foo() {
return (
<div>
<Widget code={Header.code} />
</div>
)
}
```

Each Widget component has several optional attributes, but for now you only need to know about three:

- `src` - allows you to include onchain component into your code.
- `code` - allows you to include local component into your code.
- `props` - allows you to pass props to component.
- `src` - references a path to widget code stored on the [near.social contract](https://github.com/NearSocial/social-db), follows the pattern of `${accountId}/widget/${path.to.widget}` -- this allows you to include onchain component in your code.
- `code` - allows valid, stringified widget code to be passed directly for interpretation and rendering.
- `props` - an object, allows you to pass props to the component.

### Writing Urbit-aware NEAR components

You’ll [write new components]() in `/apps/widget/components` folder.
This BOS gateway introduces a custom VM element called `<Urbit />`, which is a higher-order component to provide methods you can use to interact with the local ship. To use these methods, you must pass your Urbit-aware JSX to the element's `provides` property: `<Urbit provides={({ poke, scry}) => <>...</>} />`

This BOS gateway uses a fork of the NEAR Social VM that includes an [Urbit object](https://docs.urbit.org), and that object has methods you can use to interact with the local ship.
You can learn and modify the exposed methods in [UrbitProvider](./src/components/UrbitProvider.js).

#### `Urbit.pokeUrbit(app, mark, json)`
#### `poke(app, mark, json)`

Sends a poke (like a POST request) to the local ship.

This method takes the app you’d like to send a [poke](https://docs.urbit.org/glossary/poke) to, the [mark](https://docs.urbit.org/glossary/mark) that tells the app what kind of poke it is, and a json object with the data you’d like to send.

```
Urbit.pokeUrbit('hood', 'helm-hi', 'hello urbit!')
.then(res => {
console.log(`${pokeVal} been printed in dojo`)
})

```jsx
<Urbit
provides={({ poke }) => (
<button
onClick={() =>
poke("hood", "helm-hi", "hello urbit!").then((res) => {
console.log(`${pokeVal} been printed in dojo`);
})
}
>
poke
</button>
)}
/>
```

Documentation:

- [pokeUrbit method](https://docs.urbit.org)
- [poke method](https://docs.urbit.org)

- [Pokes](https://docs.urbit.org/courses/app-school/6-pokes)

- [Marks](https://docs.urbit.org/system/kernel/clay/guides/marks)

#### `Urbit.scryUrbit(app, path)`
#### `scry(app, path)`

Send a scry (like a GET request) to the local ship.

```
Urbit.scryUrbit('docket', '/charges')
.then(res => {
setResponse(res)
})
```jsx
<Urbit
provides={({ scry }) => (
<button
onClick={() =>
scry("docket", "/charges").then((res) => {
setResponse(res)
})
}
>
scry
</button>
)}
/>
```

Documentation:

- [scryUrbut method](https://docs.urbit.org)
- [scry method](https://docs.urbit.org)

- [Scries](https://docs.urbit.org/courses/app-school/10-scry)

#### Development methods

The Urbit object also contains two methods that are useful for development. You should remove these before deploying.

`Urbit.ship(ship)` - Sets the name of the local ship for the VM.

`Urbit.setTestApi(host, code)` - Configures port and access key authentication details for the VM.

## Learn more about Urbit

To learn more about Urbit, take a look at the following resources:
Expand All @@ -154,5 +147,28 @@ To learn more about NEAR, take a look at the following resources:

## Deploying

- [Deploying Component]()
- [Deploying BOS gateway]()
### Widgets

To deploy your widgets to the near.social contract on the NEAR blockchain, follow the [bos-workspace deploy guide](https://github.com/NEARBuilders/bos-workspace?tab=readme-ov-file#deployment) to either deploy via command line, or an automated git workflow.

In short, the command is:

```cmd
pnpm run bw deploy
```

### Gateway

To deploy your gateway, first build the distribution:

```cmd
pnpm run build
```

Inside `dist/index.html`, make a modification to the `near-social-viewer` webcomponent to use your root widget src, for example:

```html
<near-social-viewer src="urbitlabs.near/widget/app"></near-social-viewer>
```

Then follow the instructions to adding this `dist` to a glob, and uploading this glob to an S3 bucket or some other public-available endpoint.
4 changes: 4 additions & 0 deletions templates/frontend/gateway/bos.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"account": "urbitlabs.near",
"index": "urbitlabs.near/widget/app"
}
32 changes: 18 additions & 14 deletions templates/frontend/gateway/config/webpack.development.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const path = require('path')
const { HotModuleReplacementPlugin } = require('webpack')
const path = require('path');
const { HotModuleReplacementPlugin } = require('webpack');

module.exports = () => ({
devtool: false,
devtool: 'inline-source-map',
module: {
rules: [
{
Expand Down Expand Up @@ -32,23 +32,27 @@ module.exports = () => ({
},
{
// compiles Sass to CSS
loader: 'sass-loader'
}
]
}
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
publicPath: '/'
loader: 'sass-loader',
options: {
// Prefer `dart-sass`
implementation: require('sass'),
sassOptions: {
quietDeps: true,
},
},
},
],
},
],
},
devServer: {
open: true,
static: path.resolve(__dirname, '../dist'),
port: 8081,
compress: true,
historyApiFallback: true
historyApiFallback: {
disableDotRule: true,
},
},
plugins: [new HotModuleReplacementPlugin()]
})
21 changes: 17 additions & 4 deletions templates/frontend/gateway/config/webpack.production.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const path = require('path')

module.exports = () => {
Expand All @@ -14,7 +15,7 @@ module.exports = () => {
rules: [
// {
// test: /\.(css)$/,
// use: [MiniCssExtractPlugin.loader, "css-loader"],
// use: [MiniCssExtractPlugin.loader, 'css-loader'],
// // options: {
// // sourceMap: false,
// // },
Expand All @@ -34,7 +35,7 @@ module.exports = () => {
// Run postcss actions
loader: 'postcss-loader',
options: {
// `postcssOptions` is needed for postcss 8.x;
// `postcssOptions` is needed for postcss 8.x
// if you use postcss 7.x skip the key
postcssOptions: {
// postcss plugins, can be exported to postcss.config.js
Expand All @@ -46,7 +47,14 @@ module.exports = () => {
},
{
// compiles Sass to CSS
loader: 'sass-loader'
loader: 'sass-loader',
options: {
// Prefer `dart-sass`
implementation: require('sass'),
sassOptions: {
quietDeps: true
}
}
}
]
}
Expand All @@ -60,7 +68,12 @@ module.exports = () => {
],
optimization: {
minimize: true,
minimizer: [new CssMinimizerPlugin(), '...'],
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin({
exclude: /webcomponentapp.js/
})
],
runtimeChunk: {
name: 'runtime'
}
Expand Down
3 changes: 3 additions & 0 deletions templates/frontend/gateway/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"urbitlabs.near": {}
}
Loading