# @brandon.cs/bnjs

> Gelato Automate JS resolvers sdk

Latest version **0.1.37** (published 2022-11-28) · ISC license · 0 weekly downloads

## Install

```sh
npm install @brandon.cs/bnjs
pnpm add @brandon.cs/bnjs
yarn add @brandon.cs/bnjs
bun add @brandon.cs/bnjs
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.37 |
| Published | 2022-11-28 |
| First published | 2022-11-25 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 11 |
| Unpacked size | 75.7 KB |
| Known vulnerabilities | 0 (+13 in 2 direct dependencies) |
| Install scripts | no |
| Maintainers | brandon.cs |

## Links

- npm: https://www.npmjs.com/package/@brandon.cs/bnjs
- npm.io page: https://npm.io/package/@brandon.cs/bnjs

## Dependencies (11)

- [ajv](https://npm.io/package/ajv.md) ^8.11.0
- [tar](https://npm.io/package/tar.md) ^6.1.12
- [axios](https://npm.io/package/axios.md) ^1.1.2
- [colors](https://npm.io/package/colors.md) ^1.4.0
- [dotenv](https://npm.io/package/dotenv.md) ^16.0.3
- [ethers](https://npm.io/package/ethers.md) ^5.7.1
- [esbuild](https://npm.io/package/esbuild.md) ^0.15.11
- [pidusage](https://npm.io/package/pidusage.md) ^3.0.1
- [dockerode](https://npm.io/package/dockerode.md) ^3.3.4
- [form-data](https://npm.io/package/form-data.md) ^4.0.0
- [@types/dockerode](https://npm.io/package/@types/dockerode.md) ^3.3.11

## Recent versions

- 0.1.37 (latest) — 2022-11-28
- 0.1.36 — 2022-11-25
- 0.1.35 — 2022-11-25
- 0.1.34 — 2022-11-25
- 0.1.33 — 2022-11-25
- 0.1.32 — 2022-11-25
- 0.1.31 — 2022-11-25
- 0.1.30 — 2022-11-25
- 0.1.29 — 2022-11-25
- 0.1.28 — 2022-11-25
- 0.1.27 — 2022-11-25
- 0.1.26 — 2022-11-25
- 0.1.25 — 2022-11-25
- 0.1.24 — 2022-11-25
- 0.1.23 — 2022-11-25
- … 23 more at https://npm.io/package/@brandon.cs/bnjs/versions

## README

# JsResolver Proof Of Concept
Playground repo to prototype JsResolvers
<br /><br />

## Project Setup
1. Install project dependencies
```
yarn install
```

2. If you want to use a private RPC provider, 
   - Copy `.env_example` to init your own `.env` file
  ```
  cp .env_example .env
  ```
   - Complete your `.env` file with your private settings

## Write a Js Resolver

- Create a new file in `src/resolvers`
- Register your resolver main function using `JsResolverSdk.onChecker`
- Example:
```typescript
import { JsResolverSdk, JsResolverContext } from "../lib";
import { Contract, ethers } from "ethers";
import axios from "axios";

const ORACLE_ABI = [
  "function lastUpdated() external view returns(uint256)",
  "function updatePrice(uint256)",
];

JsResolverSdk.onChecker(async (context: JsResolverContext) => {
  const { userArgs, gelatoArgs, secrets } = context;

  // Use default ethers provider or your own using secrets api key
  console.log('ChainId:', context.gelatoArgs.chainId)
  const rpcProvider = ethers.getDefaultProvider(context.gelatoArgs.chainId, {
    alchemy: await secrets.get("ALCHEMY_ID"),
  });

  // Retrieve Last oracle update time
  const oracleAddress = "0x6a3c82330164822A8a39C7C0224D20DB35DD030a";
  const oracle = new Contract(oracleAddress, ORACLE_ABI, rpcProvider);
  const lastUpdated = parseInt(await oracle.lastUpdated());
  console.log(`Last oracle update: ${lastUpdated}`);

  // Check if it's ready for a new update
  const nextUpdateTime = lastUpdated + 300; // 5 min
  const timestamp = gelatoArgs.blockTime;
  console.log(`Next oracle update: ${nextUpdateTime}`);
  if (timestamp < nextUpdateTime) {
    return { canExec: false, message: `Time not elapsed` };
  }

  // Get current price on coingecko
  const currency = "ethereum";
  const priceData = await axios.get(
    `https://api.coingecko.com/api/v3/simple/price?ids=${currency}&vs_currencies=usd`
  );
  const price = Math.floor(priceData.data[currency].usd);
  console.log(`Updating price: ${price}`);

  // Return execution call data
  return {
    canExec: true,
    callData: oracle.interface.encodeFunctionData("updatePrice", [price]),
  };
});
```
- create your resolver `schema.json` to specify your runtime configuration:
```json
{
  "jsResolverVersion": "1.0.0",
  "runtime": "node-18",
  "memory": 128, 
  "timeout": 60,
  "userArgs": {}
}
```


## Test your resolver

- Use `yarn test FILENAME` command to test your resolver

- Options:
  - `--show-logs` Show internal Resolver logs
  - `--runtime=thread|docker` Use `thread` if you don't have `docker`set up locally (default: `docker`)
  - `--debug` Show Runtime debug messages
  - `--user-args=[key]:[value]` Set your Resolver user args

- Example: `yarn test src/resolvers/index.ts --show-logs --runtime=thread`
- Output:
  ```
  JsResolver Build result:
  ✓ File: ./.tmp/resolver.cjs
  ✓ File size: 1.70mb
  ✓ Build time: 109.93ms

  JsResolver running logs:
  > ChainId: 5
  > Last oracle update: 1665512172
  > Next oracle update: 1665512472
  > Updating price: 1586

  JsResolver Result:
  ✓ Return value: {
    canExec: true,
    callData: '0x8d6cc56d0000000000000000000000000000000000000000000000000000000000000632'
  }

  JsResolver Runtime stats:
  ✓ Duration: 5.41s
  ✓ Memory: 57.77mb
  ```
## Upload / fetch Js Resolver
Use `yarn upload FILENAME` command to upload your resolver.

```
> yarn upload ./src/resolvers/index.ts

## Use User arguments
1. Declare your expected `userArgs` in you schema, accepted types are 'string', 'number' or 'float':
```json
{
  "jsResolverVersion": "1.0.0",
  "runtime": "node-18",
  "memory": 128, 
  "timeout": 60,
  "userArgs": {
    "currency": "string",
    "oracle": "string"
  }
}
```

2. Access your `userArgs` from the JsResolver context:
```typescript
JsResolverSdk.onChecker(async (context: JsResolverContext) => {
  const { userArgs, gelatoArgs, secrets } = context;

  // User args:
  console.log('Currency:', userArgs.currency)
  console.log('Oracle:', userArgs.oracle)
  
});
```

1. Pass `user-args` to the CLI to test your resolver:
```
yarn test src/resolvers/oracle/index.ts --show-logs --user-args=currency:ethereum --user-args=oracle:0x6a3c82330164822A8a39C7C0224D20DB35DD030a
```

## Benchmark / Load testing

- Use `yarn benchmark FILENAME` command to run a test load

- Options:
  - all `test` command options
  - `--load=100` configure the number of resolver you want to run for your load test (default: `10`)
  - `--pool=10` configure the pool size, ie max number of concurrent worker (default: `10`)

- Example: `yarn benchmark src/resolvers/index.ts --load=100 --pool=10`
- Output:
  ```  
  Benchmark result:
  - nb success: 100/100
  - duration: 64s
  ```



## Failure tests
Some example failing file to test error handling
- Syntax error in the resolver:
  - Run: `yarn test src/resolvers/fails/syntax-error.js`
  - Result:
  ```
  JsResolver building...
  ✘ [ERROR] Could not resolve "nothing"

      src/resolvers/fails/syntax-error.js:1:30:
        1 │ import { JsResolverSdk } from "nothing";
          ╵                               ~~~~~~~~~

    You can mark the path "nothing" as external to exclude it from the bundle, which will remove this
    error.


  JsResolver Build result:
  ✗ Error: Build failed with 1 error:
  src/resolvers/fails/syntax-error.js:1:30: ERROR: Could not resolve "nothing"
  ```

- No checker function registered in the resolver:
  - Run: `yarn test src/resolvers/fails/not-registered.ts`
  - Result:
  ```
  JsResolver Result:
  ✗ Error: JsResolver start-up timeout (5s)
  Make sure you registered your checker function correctly in your script.
  ```

- Resolver run out of memory:
  - Run: `yarn test src/resolvers/fails/escape-memory.ts`
  - Result
  ```
  JsResolver Result:
  ✗ Error: JsResolver sandbox exited with code=137

  JsResolver Runtime stats:
  ✓ Duration: 1.91s
  ✗ Memory: 31.97mb
  ```

- Resolver exceed timeout:
   - Run: `yarn test src/resolvers/fails/escape-timeout.ts`
   - Result:
  ```
  JsResolver Result:
  ✗ Error: JsResolver exceed execution timeout (10s)

  JsResolver Runtime stats:
  ✗ Duration: 10.97s
  ✓ Memory: 25.34mb
  ```

- Resolver ends without returning result:
  - Run: `yarn test src/resolvers/fails/no-result.js`
  - Result:
  ```
  JsResolver Result:
  ✗ Error: JsResolver exited without returning result
  ```

---
_Source: https://npm.io/package/@brandon.cs/bnjs · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
