diff --git a/connect/README.md b/connect/README.md index b95a85864..7083b62a1 100644 --- a/connect/README.md +++ b/connect/README.md @@ -168,9 +168,17 @@ const processId = await spawn({ signer: createSigner(wallet), tags, data, + // `mainnet` mode only: the execution device the process runs on. Defaults to + // "genesis-wasm@1.0"; set e.g. "lua@5.3a" to spawn a native Lua process. + // May also be set via the EXECUTION_DEVICE environment variable. + executionDevice, }); ``` +> In `mainnet` mode, `module` must be a transaction id (a string) referencing an +> uploaded module. `executionDevice` selects the process's execution +> device (default `genesis-wasm@1.0`). + #### `connect` If you would like the connect to use ao components other than the defaults, you diff --git a/connect/src/client/ao-core.js b/connect/src/client/ao-core.js index 5f23c85e7..9a08a1d65 100644 --- a/connect/src/client/ao-core.js +++ b/connect/src/client/ao-core.js @@ -88,8 +88,13 @@ export function spawnWith(deps) { if (!scheduler) throw new Error('No scheduler provided') if (!module) throw new Error('No module provided') + if (typeof module !== 'string') { + throw new Error('module must be a transaction-id string') + } const authority = process.env.AUTHORITY || args.authority || scheduler + const executionDevice = + process.env.EXECUTION_DEVICE || args.executionDevice || 'genesis-wasm@1.0' debugLog('info', 'Node URL:', deps.url) debugLog('info', 'Scheduler:', scheduler) @@ -102,7 +107,7 @@ export function spawnWith(deps) { device: 'process@1.0', 'scheduler-device': 'scheduler@1.0', 'push-device': 'push@1.0', - 'execution-device': 'genesis-wasm@1.0', + 'execution-device': executionDevice, Authority: authority, Scheduler: scheduler, Module: module, diff --git a/connect/src/client/ao-core.spawn.unit.test.js b/connect/src/client/ao-core.spawn.unit.test.js new file mode 100644 index 000000000..40288cbce --- /dev/null +++ b/connect/src/client/ao-core.spawn.unit.test.js @@ -0,0 +1,64 @@ +import { describe, test } from 'node:test' +import * as assert from 'node:assert' +import { spawnWith } from './ao-core.js' + +// Unit tests for mainnet spawn param-building — no live node. A fake `deps` +// captures the params the client would POST. +const makeDeps = () => { + const captured = {} + return { + captured, + scheduler: 'SCHED_ADDR', + aoCore: { + request: async (params) => { + captured.params = params + return { headers: { get: (k) => (k === 'process' ? 'PID123' : null) } } + } + } + } +} + +describe('mainnet spawn: execution-device override', () => { + test('defaults to genesis-wasm@1.0 when not provided', async () => { + const deps = makeDeps() + await spawnWith(deps)({ module: 'MODTX' }) + assert.equal(deps.captured.params['execution-device'], 'genesis-wasm@1.0') + }) + + test('honors args.executionDevice', async () => { + const deps = makeDeps() + await spawnWith(deps)({ module: 'MODTX', executionDevice: 'lua@5.3a' }) + assert.equal(deps.captured.params['execution-device'], 'lua@5.3a') + }) + + test('honors EXECUTION_DEVICE env', async () => { + const prev = process.env.EXECUTION_DEVICE + process.env.EXECUTION_DEVICE = 'lua@5.3a' + try { + const deps = makeDeps() + await spawnWith(deps)({ module: 'MODTX' }) + assert.equal(deps.captured.params['execution-device'], 'lua@5.3a') + } finally { + if (prev === undefined) delete process.env.EXECUTION_DEVICE + else process.env.EXECUTION_DEVICE = prev + } + }) +}) + +describe('mainnet spawn: non-string module is rejected', () => { + test('throws on a map-valued module instead of "[object Object]"', async () => { + const deps = makeDeps() + await assert.rejects( + () => spawnWith(deps)({ module: { 'content-type': 'application/lua', body: 'x' } }), + /module must be a transaction-id string/ + ) + assert.equal(deps.captured.params, undefined, 'request must not be sent for a bad module') + }) + + test('still spawns for a valid string module', async () => { + const deps = makeDeps() + const pid = await spawnWith(deps)({ module: 'MODTX' }) + assert.equal(pid, 'PID123') + assert.equal(deps.captured.params.Module, 'MODTX') + }) +})