From d56c739eec224ef74e6a2383c65da80e7edbd12a Mon Sep 17 00:00:00 2001 From: Franklin Waller Date: Mon, 26 Aug 2024 13:45:13 +0200 Subject: [PATCH] feat(sdk): add support for proxy_http_fetch --- bun.lockb | Bin 468618 -> 469954 bytes .../assembly/index.ts | 19 ++++-- .../assembly/proxy-http.ts | 22 +++++++ .../assembly/vm-tests.ts | 2 +- .../src/proxy-http.test.ts | 61 +++++++++++++++++ libs/as-sdk/assembly/bindings/seda_v1.ts | 5 ++ libs/as-sdk/assembly/bytes.ts | 34 ++++++++++ libs/as-sdk/assembly/hex.ts | 19 ++++++ libs/as-sdk/assembly/http.ts | 41 +++++++----- libs/as-sdk/assembly/index.ts | 6 ++ libs/as-sdk/assembly/process.ts | 9 +-- libs/as-sdk/assembly/proxy-http.ts | 26 ++++++++ libs/vm/package.json | 5 +- libs/vm/src/services/keccak256.ts | 8 +++ libs/vm/src/services/try.ts | 35 ++++++++++ libs/vm/src/types/vm-actions.ts | 34 +++++++++- libs/vm/src/types/vm-promise.ts | 13 +++- libs/vm/src/vm-imports.ts | 62 +++++++++++++++++- package.json | 6 +- 19 files changed, 373 insertions(+), 34 deletions(-) create mode 100644 libs/as-sdk-integration-tests/assembly/proxy-http.ts create mode 100644 libs/as-sdk-integration-tests/src/proxy-http.test.ts create mode 100644 libs/as-sdk/assembly/bytes.ts create mode 100644 libs/as-sdk/assembly/hex.ts create mode 100644 libs/as-sdk/assembly/proxy-http.ts create mode 100644 libs/vm/src/services/keccak256.ts create mode 100644 libs/vm/src/services/try.ts diff --git a/bun.lockb b/bun.lockb index 8eec3f0a1b3059ea77b0dca138d5dbaa558a96a5..bf350402e81ffdd894c364facfe897304be79ea5 100755 GIT binary patch delta 92234 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�tRoEv-g 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

`r-6+)brD0wtzz#b_5?!?bkRJVa<@bL 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 ba;DGiuJ2`BR&t)Yn9_oVZZ2dy*tG0FLuzsT diff --git a/libs/as-sdk-integration-tests/assembly/index.ts b/libs/as-sdk-integration-tests/assembly/index.ts index 33d5bb7..407b60e 100644 --- a/libs/as-sdk-integration-tests/assembly/index.ts +++ b/libs/as-sdk-integration-tests/assembly/index.ts @@ -1,4 +1,5 @@ -import { Console, httpFetch, HttpFetchOptions, Process } from '../../as-sdk/assembly/index'; +import { Console, httpFetch, Process } from '../../as-sdk/assembly/index'; +import { testProxyHttpFetch } from './proxy-http'; import { testTallyVmReveals, testTallyVmRevealsFiltered } from './tally'; import { testTallyVmHttp, testTallyVmMode } from './vm-tests'; @@ -16,8 +17,12 @@ if (args === 'testHttpRejection') { testTallyVmReveals(); } else if (args === 'testTallyVmRevealsFiltered') { testTallyVmRevealsFiltered(); +} else if (args === 'testProxyHttpFetch') { + testProxyHttpFetch(); } +Process.exit_with_message(1, "No argument given"); + export function testHttpRejection(): void { const response = httpFetch('example.com/'); const rejected = response.rejected; @@ -35,10 +40,16 @@ export function testHttpRejection(): void { export function testHttpSuccess(): void { const response = httpFetch('https://jsonplaceholder.typicode.com/todos/1'); const fulfilled = response.fulfilled; + const rejected = response.rejected; + if (fulfilled !== null) { - Process.exit_with_result(0, fulfilled.bytes); - } else { - Process.exit_with_message(31, 'My custom test failed'); + Process.exit_with_result(0, fulfilled.bytes.value); + } + + if (rejected !== null) { + Process.exit_with_result(1, rejected.bytes.value); } + + Process.exit_with_message(20, 'Something went wrong..'); } \ No newline at end of file diff --git a/libs/as-sdk-integration-tests/assembly/proxy-http.ts b/libs/as-sdk-integration-tests/assembly/proxy-http.ts new file mode 100644 index 0000000..5ed68e0 --- /dev/null +++ b/libs/as-sdk-integration-tests/assembly/proxy-http.ts @@ -0,0 +1,22 @@ +import { Process, proxyHttpFetch } from "../../as-sdk/assembly"; + + +export function testProxyHttpFetch(): void { + const response = proxyHttpFetch('http://localhost:5384/proxy/planets/1'); + const fulfilledResponse = response.fulfilled; + const rejectedResponse = response.rejected; + + if (fulfilledResponse) { + const result = String.UTF8.decode(fulfilledResponse.bytes.value.buffer); + + Process.exit_with_message(0, result); + } + + if (rejectedResponse) { + const result = String.UTF8.decode(rejectedResponse.bytes.value.buffer); + + Process.exit_with_message(1, result); + } + + Process.exit_with_message(20, "Something went wrong.."); +} \ No newline at end of file diff --git a/libs/as-sdk-integration-tests/assembly/vm-tests.ts b/libs/as-sdk-integration-tests/assembly/vm-tests.ts index f0babd5..ee2ed8c 100644 --- a/libs/as-sdk-integration-tests/assembly/vm-tests.ts +++ b/libs/as-sdk-integration-tests/assembly/vm-tests.ts @@ -20,6 +20,6 @@ export function testTallyVmHttp(): void { } if (rejected !== null) { - Process.exit_with_result(0, rejected.bytes); + Process.exit_with_result(0, rejected.bytes.value); } } diff --git a/libs/as-sdk-integration-tests/src/proxy-http.test.ts b/libs/as-sdk-integration-tests/src/proxy-http.test.ts new file mode 100644 index 0000000..c4d681b --- /dev/null +++ b/libs/as-sdk-integration-tests/src/proxy-http.test.ts @@ -0,0 +1,61 @@ +import { expect, describe, it, mock, beforeEach } from 'bun:test'; +import { executeDrWasm } from '@seda/dev-tools'; +import { readFile } from 'node:fs/promises'; +import { Response } from 'node-fetch'; + +const mockHttpFetch = mock(); + +describe('ProxyHttp', () => { + beforeEach(() => { + mockHttpFetch.mockReset(); + }); + + it.skip('should allow proxy_http_fetch which have a valid signature', async () => { + const wasmBinary = await readFile( + 'dist/libs/as-sdk-integration-tests/debug.wasm' + ); + + const mockResponse = new Response('"Tatooine"', { + headers: { + 'x-seda-signature': '93c67407c95f7d8252d8a28f5a637d57f2088376fcf34751d3ca04324e74d8185d11fe3fb23532f610158393b5678aeda82a56898fa95e0ca4d483e7aa472715', + 'x-seda-publickey': '02100efce2a783cc7a3fbf9c5d15d4cc6e263337651312f21a35d30c16cb38f4c3' + }, + }); + + mockHttpFetch.mockResolvedValue(mockResponse); + + const result = await executeDrWasm( + wasmBinary, + Buffer.from('testProxyHttpFetch'), + mockHttpFetch + ); + + expect(result.exitCode).toBe(0); + expect(result.result).toEqual(new TextEncoder().encode('"Tatooine"')); + }); + + it.skip('should reject if the proxy_http_fetch has an invalid signature', async () => { + const wasmBinary = await readFile( + 'dist/libs/as-sdk-integration-tests/debug.wasm' + ); + + const mockResponse = new Response('"Tatooine"', { + statusText: 'mock_ok', + headers: { + 'x-seda-signature': '83c67407c95f7d8252d8a28f5a637d57f2088376fcf34751d3ca04324e74d8185d11fe3fb23532f610158393b5678aeda82a56898fa95e0ca4d483e7aa472715', + 'x-seda-publickey': '02100efce2a783cc7a3fbf9c5d15d4cc6e263337651312f21a35d30c16cb38f4c3' + }, + }); + + mockHttpFetch.mockResolvedValue(mockResponse); + + const result = await executeDrWasm( + wasmBinary, + Buffer.from('testProxyHttpFetch'), + mockHttpFetch + ); + + expect(result.exitCode).toBe(1); + expect(result.result).toEqual(new TextEncoder().encode('Invalid signature')); + }); +}); diff --git a/libs/as-sdk/assembly/bindings/seda_v1.ts b/libs/as-sdk/assembly/bindings/seda_v1.ts index 198b717..f6f1a26 100644 --- a/libs/as-sdk/assembly/bindings/seda_v1.ts +++ b/libs/as-sdk/assembly/bindings/seda_v1.ts @@ -3,6 +3,11 @@ export declare function http_fetch( action_length: u32 ): u32; +export declare function proxy_http_fetch( + action_ptr: usize, + action_length: u32 +): u32; + export declare function call_result_write( result: usize, result_length: u32 diff --git a/libs/as-sdk/assembly/bytes.ts b/libs/as-sdk/assembly/bytes.ts new file mode 100644 index 0000000..a883880 --- /dev/null +++ b/libs/as-sdk/assembly/bytes.ts @@ -0,0 +1,34 @@ +import { JSON } from "json-as"; +import { decodeHex, encodeHex } from "./hex"; + +@json +class InnerBytes { + type: string = "hex"; + value!: string; +} + +export class Bytes { + type: string = "hex"; + value: Uint8Array; + + constructor(value: Uint8Array) { + this.value = value; + } + + __SERIALIZE(): string { + const inner = new InnerBytes(); + inner.value = encodeHex(this.value); + + return JSON.stringify(inner); + } + + __INITIALIZE(): void {} + + __DESERIALIZE(data: string, _key_start: i32, _key_end: i32, _outerLoopIndex: i32, _numberValueIndex: i32): bool { + const innerBytes = JSON.parse(data); + const buffer = decodeHex(innerBytes.value); + this.value = buffer; + + return true; + } +} diff --git a/libs/as-sdk/assembly/hex.ts b/libs/as-sdk/assembly/hex.ts new file mode 100644 index 0000000..ba1fdfc --- /dev/null +++ b/libs/as-sdk/assembly/hex.ts @@ -0,0 +1,19 @@ +export function encodeHex(array: Uint8Array): string { + let hex = '' + + for (let i = 0; i < array.length; i++) { + hex += array[i].toString(16) + } + + return hex +} + +export function decodeHex(data: string): Uint8Array { + let array = new Uint8Array(data.length >>> 1) + + for (let i = 0; i < data.length >>> 1; ++i) { + array.fill(i32(parseInt('0x' + data.substr(i * 2, 2), 16)), i, i + 1) + } + + return array; +} diff --git a/libs/as-sdk/assembly/http.ts b/libs/as-sdk/assembly/http.ts index 02be8fd..6ec035f 100644 --- a/libs/as-sdk/assembly/http.ts +++ b/libs/as-sdk/assembly/http.ts @@ -2,9 +2,10 @@ import { JSON } from 'json-as/assembly'; import { call_result_write, http_fetch } from './bindings/seda_v1'; import { jsonArrToUint8Array, uint8arrayToJsonArray } from './json-utils'; import { PromiseStatus, FromBuffer } from './promise'; +import { Bytes } from './bytes'; @json -class InnerResponse { +export class InnerHttpResponse { bytes!: u8[]; content_length!: i64; status!: i64; @@ -12,19 +13,25 @@ class InnerResponse { headers!: Map; } +@json +export class HttpResponseDisplay { + type: string = "HttpResponseDisplay"; + bytes!: Bytes; + contentLength!: i64; + url!: string; + status!: i64; + headers!: Map; +} + /** * Response of an httpFetch call */ @json export class HttpResponse implements FromBuffer { - /** - * Raw result of the HTTP fetch. (usually not used) - */ - public result: Uint8Array | null = null; /** * The response body result. This can be used to convert to JSON, text, etc. */ - public bytes: Uint8Array = new Uint8Array(0); + public bytes: Bytes = new Bytes(new Uint8Array(0)); /** * The length of the content */ @@ -42,12 +49,11 @@ export class HttpResponse implements FromBuffer { */ public headers: Map = new Map(); - fromBuffer(buffer: Uint8Array): HttpResponse { + static fromInner(value: InnerHttpResponse): HttpResponse { const response = new HttpResponse(); - const value = JSON.parse(String.UTF8.decode(buffer.buffer)); - + if (value.bytes) { - response.bytes = jsonArrToUint8Array(value.bytes); + response.bytes.value = jsonArrToUint8Array(value.bytes); } if (value.content_length) { @@ -76,15 +82,20 @@ export class HttpResponse implements FromBuffer { } } - response.result = buffer; return response; } + fromBuffer(buffer: Uint8Array): HttpResponse { + const value = JSON.parse(String.UTF8.decode(buffer.buffer)); + + return HttpResponse.fromInner(value); + } + toString(): string { - const response = new InnerResponse(); + const response = new HttpResponseDisplay(); - response.bytes = uint8arrayToJsonArray(this.bytes); - response.content_length = this.contentLength; + response.bytes = this.bytes; + response.contentLength = this.contentLength; response.headers = this.headers; response.status = this.status; response.url = this.url; @@ -131,7 +142,7 @@ export class HttpFetchOptions { } @json -class HttpFetch { +export class HttpFetch { url: string; options: HttpFetchOptions; diff --git a/libs/as-sdk/assembly/index.ts b/libs/as-sdk/assembly/index.ts index ae34efd..9200f91 100644 --- a/libs/as-sdk/assembly/index.ts +++ b/libs/as-sdk/assembly/index.ts @@ -8,9 +8,15 @@ export { HttpResponse, } from './http'; +export { + proxyHttpFetch, +} from "./proxy-http"; + // Export library so consumers don't need to reimport it themselves export { JSON } from 'json-as/assembly'; export { PromiseStatus } from './promise'; export { Process, Tally }; export { RevealBody } from './tally'; export { Console } from './console'; +export { Bytes } from './bytes'; +export { decodeHex, encodeHex } from './hex'; \ No newline at end of file diff --git a/libs/as-sdk/assembly/process.ts b/libs/as-sdk/assembly/process.ts index b60f2ae..536b6b8 100644 --- a/libs/as-sdk/assembly/process.ts +++ b/libs/as-sdk/assembly/process.ts @@ -1,6 +1,7 @@ import { VM_MODE_TALLY, VM_MODE_DR, VM_MODE_ENV_KEY } from './vm-modes'; import { wasi_process } from '@assemblyscript/wasi-shim/assembly/wasi_process'; import { execution_result } from './bindings/seda_v1'; +import { decodeHex } from './hex'; export default class Process { /** @@ -48,14 +49,8 @@ export default class Process { static getInputs(): Uint8Array { // Data at index 0 is the dr/tally inputs encoded as hex const data = Process.args().at(1); - const array = new Uint8Array(data.length >>> 1) - // Decodes the hex string into a buffer - for (let i = 0; i < data.length >>> 1; ++i) { - array.fill(i32(parseInt('0x' + data.substr(i * 2, 2), 16)), i, i + 1) - } - - return array; + return decodeHex(data); } /** diff --git a/libs/as-sdk/assembly/proxy-http.ts b/libs/as-sdk/assembly/proxy-http.ts new file mode 100644 index 0000000..149dec7 --- /dev/null +++ b/libs/as-sdk/assembly/proxy-http.ts @@ -0,0 +1,26 @@ +import { JSON } from 'json-as/assembly'; +import { HttpFetchOptions, HttpFetch, HttpResponse } from "./http"; +import { call_result_write, proxy_http_fetch } from './bindings/seda_v1'; +import { PromiseStatus } from './promise'; + +export function proxyHttpFetch(url: string, options: HttpFetchOptions = new HttpFetchOptions()): PromiseStatus { + const action = new HttpFetch(url, options); + const actionStr = JSON.stringify(action); + + const buffer = String.UTF8.encode(actionStr); + const utf8ptr = changetype(buffer); + + const responseLength = proxy_http_fetch(utf8ptr, buffer.byteLength); + const responseBuffer = new ArrayBuffer(responseLength); + const responseBufferPtr = changetype(responseBuffer); + + call_result_write(responseBufferPtr, responseLength); + + const response = String.UTF8.decode(responseBuffer); + + return PromiseStatus.fromStr( + response, + new HttpResponse(), + new HttpResponse(), + ); +} \ No newline at end of file diff --git a/libs/vm/package.json b/libs/vm/package.json index d46d8f0..e798603 100644 --- a/libs/vm/package.json +++ b/libs/vm/package.json @@ -3,6 +3,9 @@ "type": "module", "version": "0.0.3", "dependencies": { - "@wasmer/wasi": "^1.2.2" + "@wasmer/wasi": "^1.2.2", + "true-myth": "^7.3.0", + "@noble/secp256k1": "2.1.0", + "@noble/hashes": "1.4.0" } } diff --git a/libs/vm/src/services/keccak256.ts b/libs/vm/src/services/keccak256.ts new file mode 100644 index 0000000..e5b3be7 --- /dev/null +++ b/libs/vm/src/services/keccak256.ts @@ -0,0 +1,8 @@ +import { keccak_256 } from "@noble/hashes/sha3"; + +export function keccak256(input: Buffer): Buffer { + const hasher = keccak_256.create(); + hasher.update(input); + + return Buffer.from(hasher.digest()); +} \ No newline at end of file diff --git a/libs/vm/src/services/try.ts b/libs/vm/src/services/try.ts new file mode 100644 index 0000000..8b0dde4 --- /dev/null +++ b/libs/vm/src/services/try.ts @@ -0,0 +1,35 @@ +import { Result } from "true-myth"; +import * as v from "valibot"; + +export function trySync(callback: () => T): Result { + try { + return Result.ok(callback()); + } catch (error) { + return Result.err(error); + } +} + +export async function tryAsync( + callback: () => Promise, +): Promise> { + try { + return Result.ok(await callback()); + } catch (error) { + return Result.err(error); + } +} + +type SafeParseArguments = Parameters; +export function tryParseSync>( + schema: T, + input: SafeParseArguments[1], + info?: SafeParseArguments[2], +): Result, v.GenericIssue[]> { + const result = v.safeParse(schema, input, info); + + if (result.success) { + return Result.ok(result.output); + } + + return Result.err(result.issues); +} diff --git a/libs/vm/src/types/vm-actions.ts b/libs/vm/src/types/vm-actions.ts index 3c4d50c..ac38f61 100644 --- a/libs/vm/src/types/vm-actions.ts +++ b/libs/vm/src/types/vm-actions.ts @@ -1,4 +1,4 @@ -import type { ToBuffer } from "./vm-promise"; +import { PromiseStatus, PromiseStatusResult, ToBuffer } from "./vm-promise"; enum HttpFetchMethod { Options = 'Options', @@ -46,6 +46,38 @@ export class HttpFetchResponse implements ToBuffer { toBuffer(): Uint8Array { return new TextEncoder().encode(JSON.stringify(this.data)); } + + static createRejectedPromise(error: string): PromiseStatus { + const errorBytes = Array.from(new TextEncoder().encode(error)); + + return PromiseStatus.rejected(new HttpFetchResponse({ + bytes: errorBytes, + content_length: errorBytes.length, + headers: {}, + status: 0, + url: '', + })); + } + + static fromPromise(input: PromiseStatus): HttpFetchResponse { + if (input.value.Fulfilled) { + const fulfilled = Buffer.from(input.value.Fulfilled).toString('utf-8'); + return new HttpFetchResponse(JSON.parse(fulfilled)); + } + + if (input.value.Rejected) { + const rejected = Buffer.from(input.value.Rejected).toString('utf-8'); + return new HttpFetchResponse(JSON.parse(rejected)); + } + + return new HttpFetchResponse({ + bytes: [], + content_length: 0, + headers: {}, + status: 0, + url: '' + }); + } } export type VmAction = HttpFetchAction; diff --git a/libs/vm/src/types/vm-promise.ts b/libs/vm/src/types/vm-promise.ts index df96dd9..b283e69 100644 --- a/libs/vm/src/types/vm-promise.ts +++ b/libs/vm/src/types/vm-promise.ts @@ -1,4 +1,4 @@ -interface PromiseStatusResult { +export interface PromiseStatusResult { /** Actually a Uint8[] */ Fulfilled?: number[]; /** Actually a Uint8[] */ @@ -10,7 +10,16 @@ export interface ToBuffer { } export class PromiseStatus { - private constructor(private value: PromiseStatusResult) {} + private constructor(public value: PromiseStatusResult) {} + + static fromBuffer(value: Buffer): PromiseStatus { + const raw: PromiseStatusResult = JSON.parse(value.toString('utf-8')); + + return new PromiseStatus({ + Fulfilled: raw.Fulfilled, + Rejected: raw.Rejected, + }); + } static rejected(value: T): PromiseStatus { return new PromiseStatus({ diff --git a/libs/vm/src/vm-imports.ts b/libs/vm/src/vm-imports.ts index a908254..91157c1 100644 --- a/libs/vm/src/vm-imports.ts +++ b/libs/vm/src/vm-imports.ts @@ -1,11 +1,16 @@ -import type { HttpFetchAction } from './types/vm-actions'; +import { HttpFetchResponse, type HttpFetchAction } from './types/vm-actions'; +import { PromiseStatus } from './types/vm-promise'; import { WorkerToHost } from './worker-host-communication.js'; +import { Maybe } from "true-myth"; +import * as Secp256k1 from "@noble/secp256k1"; +import { keccak256 } from './services/keccak256'; export default class VmImports { memory?: WebAssembly.Memory; workerToHost: WorkerToHost; callResult: Uint8Array = new Uint8Array(); result: Uint8Array = new Uint8Array(); + usedPublicKeys: string[] = []; processId: string; constructor(notifierBuffer: SharedArrayBuffer, processId: string) { @@ -17,6 +22,60 @@ export default class VmImports { this.memory = memory; } + /** + * TODO: This function also must create the x-seda-proof the same way the overlay node does it + * TODO: This function must be modified to make the verification the same as the data proxy side + * @param action + * @param actionLength + * @returns + */ + proxyHttpFetch(action: number, actionLength: number) { + const rawAction = new Uint8Array( + this.memory?.buffer.slice(action, action + actionLength) ?? [] + ); + const messageRaw = Buffer.from(rawAction).toString('utf-8'); + + try { + const message: HttpFetchAction = JSON.parse(messageRaw); + const rawResponse = Buffer.from(this.workerToHost.callActionOnHost(message)); + const httpResponse = HttpFetchResponse.fromPromise(PromiseStatus.fromBuffer(rawResponse)); + + const signatureRaw = Maybe.of(httpResponse.data.headers['x-seda-signature']); + const publicKeyRaw = Maybe.of(httpResponse.data.headers['x-seda-publickey']); + + if (!signatureRaw.isJust) { + this.callResult = HttpFetchResponse.createRejectedPromise("Header x-seda-signature was not available").toBuffer(); + return this.callResult.length; + } + + if (!publicKeyRaw.isJust) { + this.callResult = HttpFetchResponse.createRejectedPromise("Header x-seda-publickey was not available").toBuffer(); + return this.callResult.length; + } + + // Verify the signature: + const signature = Buffer.from(signatureRaw.value, 'hex'); + const publicKey = Buffer.from(publicKeyRaw.value, 'hex'); + const signedMessage = keccak256(Buffer.from(httpResponse.data.bytes)); + const isValidSignature = Secp256k1.verify(signature, signedMessage, publicKey); + + if (!isValidSignature) { + this.callResult = HttpFetchResponse.createRejectedPromise("Invalid signature").toBuffer(); + return this.callResult.length; + } + + this.usedPublicKeys.push(publicKeyRaw.value); + + this.callResult = rawResponse; + return this.callResult.length; + } catch (error) { + console.error(`[${this.processId}] - @httpFetch: ${messageRaw}`, error); + this.callResult = new Uint8Array(); + + return 0; + } + } + httpFetch(action: number, actionLength: number) { const rawAction = new Uint8Array( this.memory?.buffer.slice(action, action + actionLength) ?? [] @@ -56,6 +115,7 @@ export default class VmImports { // we should restrict it to only a few ...wasiImports, seda_v1: { + proxy_http_fetch: this.httpFetch.bind(this), http_fetch: this.httpFetch.bind(this), call_result_write: this.callResultWrite.bind(this), execution_result: this.executionResult.bind(this), diff --git a/package.json b/package.json index 4be2114..4bcc32d 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "start": "bun run build && node dist/libs/vm/src/index.js", "build": "nx run-many --all --target=build", + "cli": "bun run libs/dev-tools/bin/index.js", "test": "bun run build && NODE_OPTIONS=--experimental-vm-modules nx run-many --all --target=test", "docs": "typedoc libs/as-sdk/assembly/index.ts --tsconfig ./libs/as-sdk/assembly/tsconfig.json --skipErrorChecking", "cli:generate": "cd libs/cli/proto && npx buf generate" @@ -31,7 +32,7 @@ "@types/figlet": "^1.5.6", "@types/node": "18.19.9", "@typescript-eslint/eslint-plugin": "7.9.0", - "assemblyscript": "^0.27.11", + "assemblyscript": "0.27.11", "bun-plugin-dts": "^0.2.3", "esbuild": "0.19.9", "eslint": "8.57.0", @@ -52,6 +53,7 @@ "@types/node-gzip": "^1.1.1", "@wasmer/wasi": "^1.2.2", "big.js": "^6.2.1", + "@noble/secp256k1": "2.1.0", "commander": "^11.0.0", "cosmjs-types": "^0.9.0", "dotenv": "^16.3.1", @@ -64,6 +66,6 @@ "true-myth": "^7.3.0", "tslib": "^2.3.0", "valibot": "^0.35.0", - "visitor-as": "^0.11.4" + "visitor-as": "0.11.4" } }