diff --git a/sdk/README.md b/sdk/README.md index a8279331e..74e7eb8d6 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -21,6 +21,7 @@ interacting with `ao` Smart Contracts. - [`createDataItemSigner`](#createdataitemsigner) - [Debug Logging](#debug-logging) - [Testing](#testing) +- [Project Structure](#project-structure) @@ -150,3 +151,32 @@ interested in. Run `npm test` to run the tests. Run `npm run test:integration` to run the integration tests. + +## Project Structure + +The `ao` SDK project loosely implements the +[Ports and Adapters](https://medium.com/idealo-tech-blog/hexagonal-ports-adapters-architecture-e3617bcf00a0) +Architecture. + +All business logic is in `lib` where each public api is implemented and tested. + +`dal.js` contains the contracts for the driven adapters aka side-effects. +Implementations for those contracts are injected into, then parsed and invoked +by, the business logic. This is how we inject specific integrations for +providers ie. `Warp`, `Irys`, or even platforms specific implementations like +`node` and the `browser` while keeping them separated from the business logic -- +the business logic simply consumes a black-box API -- easy to stub, and easy to +unit test. + +Because the contract wrapping is done by the business logic itself, it also +ensures the stubs we use in our unit tests accurately implement the contract +API. Thus our unit tests are simoultaneously contract tests. + +`client` contains implementations, of the contracts in `dal.js`, for various +platforms. The unit tests for the implementations in `client` also import +contracts from `dal.js` to help ensure that the implementation properly +satisfies the API. + +Finally, the entrypoints (`index.js` for Node and `index.browser.js` for the +Browser) orchestrate everything, choosing the appropriate implementations from +`client` and injecting them into the business logic from `lib`. diff --git a/sdk/src/client/browser/wallet.js b/sdk/src/client/browser/wallet.js index b037ed34a..9a76edc36 100644 --- a/sdk/src/client/browser/wallet.js +++ b/sdk/src/client/browser/wallet.js @@ -57,6 +57,9 @@ export function createDataItemSigner (arweaveWallet) { * * injecting side effects allows stubbing arweave and arweaveWallet * for the purpose of testing + * + * Currently unused, as the impl instead uses Irys to deploy contracts, + * but keeping for posterity (it's tree-shaken out in distribution bundles anyway) */ export function deployContractWith ({ logger: _logger, arweave, arweaveWallet }) { const logger = _logger.child('web-wallet:deployContract') diff --git a/sdk/src/client/warp-gateway.js b/sdk/src/client/warp-gateway.js index 0a7bc34a9..dff4a9239 100644 --- a/sdk/src/client/warp-gateway.js +++ b/sdk/src/client/warp-gateway.js @@ -5,6 +5,9 @@ import { z } from 'zod' /** * Inject dependencies, so they are configurable, * and stubbable for testing + * + * Currently unused, as the impl instead uses Irys to deploy contracts, + * but keeping for posterity (it's tree-shaken out in distribution bundles anyway) */ export function deployContractWith ({ fetch, WARP_GATEWAY_URL, logger: _logger, getTime = () => new Date().getTime() }) { const logger = _logger.child('warp-gateway:deployContract') diff --git a/servers/mu/src/config.js b/servers/mu/src/config.js index 0db8af356..fd2798f4e 100644 --- a/servers/mu/src/config.js +++ b/servers/mu/src/config.js @@ -1,3 +1,4 @@ + if (!process.env.WALLET) { console.error( "Please pass a WALLET into the environment. eg. process.env.WALLET should be your JWK string." diff --git a/servers/mu/src/domain/clients/cu.js b/servers/mu/src/domain/clients/cu.js index b27723feb..f425b16e9 100644 --- a/servers/mu/src/domain/clients/cu.js +++ b/servers/mu/src/domain/clients/cu.js @@ -1,3 +1,5 @@ +import config from '../../config.js' + const cuClient = { result: async function (cuAddress, txId) { console.log(`${cuAddress}/result/${txId}`) @@ -17,7 +19,7 @@ const cuClient = { selectNode: async function (contractId) { console.log(`Selecting cu for contract ${contractId}`) - return 'http://localhost:3005' + return config.cuUrl } } diff --git a/servers/mu/src/domain/lib/crank/crank.js b/servers/mu/src/domain/lib/crank/crank.js index 3aea4603e..9d157b265 100644 --- a/servers/mu/src/domain/lib/crank/crank.js +++ b/servers/mu/src/domain/lib/crank/crank.js @@ -23,13 +23,9 @@ function crankListWith ({ processMsg, processSpawn, logger }) { // Process spawns when the recursion terminates if (ctx.spawns && ctx.spawns.length > 0) { for (const spawn of ctx.spawns) { - try { - await of({ cachedSpawn: spawn }) - .chain(processSpawn) - .toPromise() - } catch (e) { - - } + await of({ cachedSpawn: spawn }) + .chain(processSpawn) + .toPromise() } } diff --git a/servers/mu/src/middleware/index.js b/servers/mu/src/middleware/index.js index 3c649ec62..c99b74e3a 100644 --- a/servers/mu/src/middleware/index.js +++ b/servers/mu/src/middleware/index.js @@ -1,4 +1,5 @@ import bodyParser from 'body-parser' +import cors from 'cors' import errors from './errors/errors.js' @@ -12,6 +13,7 @@ function injectDomain (req, _res, next) { } const mountMiddlewares = (app) => [ + cors(), bodyParser.json(), bodyParser.urlencoded({ extended: false }), injectDomain, diff --git a/servers/testscripts/src/test-su.js b/servers/testscripts/src/test-su.js new file mode 100644 index 000000000..a09036903 --- /dev/null +++ b/servers/testscripts/src/test-su.js @@ -0,0 +1,34 @@ +// const fs = require('fs') +// const path = require('path') + +// globalThis.MU_URL = 'http://localhost:3004' +// globalThis.CU_URL = 'http://localhost:3005' +// const { createDataItemSigner } = require('@permaweb/ao-sdk') + +// const CONTRACT_TX_ID = 'uJFN44vrnt4aLb4hBtfBryY-2z3ag_Us-e896ZaJxHM' +// const SEQUENCER_URL = 'http://localhost:9000' + +// (async function () { +// console.log('Testing ao...') + +// const walletPath = process.env.PATH_TO_WALLET + +// const walletKey = JSON.parse(fs.readFileSync(path.resolve(walletPath), 'utf8')) +// const signer = createDataItemSigner(walletKey) + +// const input = { function: 'noop' } +// const tags = [] + +// const response = await fetch( +// `${SEQUENCER_URL}/write`, +// { +// method: 'POST', +// headers: { +// 'Content-Type': 'application/octet-stream', +// Accept: 'application/json' +// }, +// body: rawDataBuffer +// } +// ) + +// })()