From 64f61f0c321dc0b38b042e88a5fd640d81dc7652 Mon Sep 17 00:00:00 2001 From: okjodom Date: Mon, 24 Aug 2026 13:27:14 +0300 Subject: [PATCH 1/2] chore: use @minmoto/sdk package name --- AGENTS.md | 4 ++-- CHANGELOG.md | 2 +- README.md | 8 ++++---- package-lock.json | 4 ++-- package.json | 2 +- release-please-config.json | 2 +- scripts/test-package.mjs | 6 +++--- scripts/vendor-upstream.mjs | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 66c306d..094e49d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Purpose -This repository publishes `@minmo/sdk`, the server-side, API-key-only facade for +This repository publishes `@minmoto/sdk`, the server-side, API-key-only facade for the Minmo Partner API. The implementation is built in private `minmoto/mini`; this repository owns the stable public constructor, export boundary, documentation, packaging, and releases. @@ -52,7 +52,7 @@ required. ## Updating the upstream artifact Use a detached, clean Mini worktree at the intended commit. Build `@minmo/core` -before `@minmo/sdk`, then run: +before the private SDK workspace, then run: ```sh npm run vendor:upstream -- --worktree /path/to/mini-worktree diff --git a/CHANGELOG.md b/CHANGELOG.md index f0ec418..3926b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,3 @@ # Changelog -Notable changes to `@minmo/sdk` will be recorded here by Release Please. +Notable changes to `@minmoto/sdk` will be recorded here by Release Please. diff --git a/README.md b/README.md index 76e0381..7064e9e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# @minmo/sdk +# @minmoto/sdk The server-side TypeScript client for Minmo Partners. @@ -9,13 +9,13 @@ and defaults to the Minmo production API. ## Install ```sh -npm install @minmo/sdk +npm install @minmoto/sdk ``` ## Quick start ```ts -import { MinmoClient } from "@minmo/sdk"; +import { MinmoClient } from "@minmoto/sdk"; const minmo = new MinmoClient({ partnerId: process.env.MINMO_PARTNER_ID!, @@ -42,7 +42,7 @@ configured Partner without a separate `forPartner()` setup call. ## Authentication and security -`@minmo/sdk` supports only Partner API-key authentication. It sends the key in +`@minmoto/sdk` supports only Partner API-key authentication. It sends the key in the `X-API-Key` request header and does not export bearer-token or token-provider authentication helpers. diff --git a/package-lock.json b/package-lock.json index c30ce95..8417d8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@minmo/sdk", + "name": "@minmoto/sdk", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@minmo/sdk", + "name": "@minmoto/sdk", "version": "0.1.0", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 41df868..4a149e4 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@minmo/sdk", + "name": "@minmoto/sdk", "version": "0.1.0", "description": "Server-side TypeScript client for the Minmo Partner API.", "type": "module", diff --git a/release-please-config.json b/release-please-config.json index 361c519..feaae60 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -3,7 +3,7 @@ "packages": { ".": { "release-type": "node", - "package-name": "@minmo/sdk", + "package-name": "@minmoto/sdk", "include-v-in-tag": true, "changelog-sections": [ { "type": "feat", "section": "Features" }, diff --git a/scripts/test-package.mjs b/scripts/test-package.mjs index 447de65..e691525 100644 --- a/scripts/test-package.mjs +++ b/scripts/test-package.mjs @@ -25,7 +25,7 @@ execFileSync("npm", ["install", "--ignore-scripts", join(fixture, packed.filenam writeFileSync( join(fixture, "consumer.mjs"), [ - 'import * as sdk from "@minmo/sdk";', + 'import * as sdk from "@minmoto/sdk";', 'if (typeof sdk.MinmoClient !== "function") throw new Error("MinmoClient missing");', 'if ("MinmoAuth" in sdk) throw new Error("MinmoAuth must not be public");', 'new sdk.MinmoClient({ partnerId: "partner-1", apiKey: "secret" });', @@ -36,7 +36,7 @@ execFileSync("node", [join(fixture, "consumer.mjs")], { stdio: "inherit" }); writeFileSync( join(fixture, "consumer.ts"), [ - 'import { Currency, MinmoClient, PaymentChannel, type MinmoClientOptions } from "@minmo/sdk";', + 'import { Currency, MinmoClient, PaymentChannel, type MinmoClientOptions } from "@minmoto/sdk";', "const options: MinmoClientOptions = { partnerId: \"partner-1\", apiKey: \"secret\" };", "const client: MinmoClient = new MinmoClient(options);", "void client.account.get;", @@ -66,7 +66,7 @@ execFileSync( ); const installedPackage = JSON.parse( - readFileSync(join(fixture, "node_modules", "@minmo", "sdk", "package.json"), "utf8"), + readFileSync(join(fixture, "node_modules", "@minmoto", "sdk", "package.json"), "utf8"), ); if (installedPackage.dependencies && Object.keys(installedPackage.dependencies).length) { throw new Error("The public SDK must not have runtime dependencies"); diff --git a/scripts/vendor-upstream.mjs b/scripts/vendor-upstream.mjs index c9d04b6..7775cf8 100644 --- a/scripts/vendor-upstream.mjs +++ b/scripts/vendor-upstream.mjs @@ -23,8 +23,8 @@ const sdkSource = join(worktree, "packages", "sdk", "src"); const coreSource = join(worktree, "packages", "core", "src", "index.ts"); assertCleanWorktree(worktree); -assertDirectory(sdkDist, "Build @minmo/sdk in the clean worktree first"); -assertDirectory(coreDist, "Build @minmo/core in the clean worktree first"); +assertDirectory(sdkDist, "Build the private SDK workspace in the clean worktree first"); +assertDirectory(coreDist, "Build the private core workspace in the clean worktree first"); rmSync(vendorRoot, { recursive: true, force: true }); mkdirSync(vendorRoot, { recursive: true }); From 4f14298ed400edada3d8220021dcfe2cb73f712f Mon Sep 17 00:00:00 2001 From: okjodom Date: Mon, 24 Aug 2026 13:41:46 +0300 Subject: [PATCH 2/2] docs: make README developer-first --- README.md | 204 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 159 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 7064e9e..a7082f9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,39 @@ # @minmoto/sdk -The server-side TypeScript client for Minmo Partners. +Build server-side Minmo Partner integrations in TypeScript. -The public package is a small API-key-only facade over the SDK implementation -maintained in the private Minmo monorepo. It binds one Partner when constructed -and defaults to the Minmo production API. +`@minmoto/sdk` is the typed Node.js client for the +[Minmo](https://www.minmo.to) Partner API. It gives you one Partner-bound +interface for bringing Bitcoin and local-currency workflows into your own +services: quote rates, coordinate OTC swaps and agents, operate wallets and +escrow, create Minmo Pay stores and invoices, and consume live domain events. + +Create a client with your Partner ID and API key, then start calling +Partner-scoped resources. The production API is configured by default, so +there is no separate `forPartner()` step or browser-oriented authentication +flow. + +## Why use the SDK? + +- **Partner-bound by default.** Every client starts in the Partner context you + provide, making the intended request scope explicit. +- **Typed from request to response.** TypeScript declarations cover inputs, + resources, events, errors, currencies, payment channels, and domain states. +- **Built for backend services.** Authentication is intentionally limited to + Partner API keys and the package targets Node.js server runtimes. +- **Small deployment surface.** The package ships as ESM with no runtime + dependencies. +- **Useful defaults.** Minmo's production API URL is configured automatically, + with an optional `baseUrl` for another Minmo deployment. + +## Requirements + +- Node.js 22 or newer +- A Minmo Partner ID +- A Partner API key with the capabilities required by your integration + +Partner API keys are server secrets. Keep them in a secrets manager or private +server environment; never expose them to browser or mobile clients. ## Install @@ -22,71 +51,156 @@ const minmo = new MinmoClient({ apiKey: process.env.MINMO_API_KEY!, }); -const account = await minmo.account.get(); -const stores = await minmo.integrations.pay.listStores(); +const partner = await minmo.account.get(); + +console.log(`Connected to ${partner.displayName}`); ``` -`baseUrl` is optional and defaults to `https://api.minmo.to/api/v1`: +`MinmoClient` requires a non-empty Partner ID and API key, then sends the key in +the `X-API-Key` header. Calls such as `account.get()`, `settings.get()`, and +`integrations.pay.listStores()` automatically use the configured Partner. + +## What you can build + +| Area | Client | Use it to | +| --- | --- | --- | +| Partner operations | `account`, `settings`, `analytics`, `members`, `invitations`, `apiKeys`, `referrals` | Manage the Partner account, team access, reporting, API keys, and referrals | +| Minmo Pay | `integrations.pay` | Create stores and invoices, connect settlement wallets, read authoritative invoice state, and subscribe to Pay events | +| OTC | `otc.rates`, `otc.swap`, `otc.agents` | Quote Bitcoin and local-currency rates, coordinate swaps, and operate an agent network | +| Wallets | `wallet` | Create and manage wallets, receive or send funds, transfer balances, and inspect wallet activity | +| Escrow | `escrow` | Create and reconcile escrows, verify funding, release or refund funds, and manage disputes | +| Events | `events` and domain subscriptions | React to Partner, Pay, OTC, wallet, and escrow changes with typed events | + +For example, request a typed BTC/KES quote and list the Partner's Minmo Pay +stores: ```ts -const staging = new MinmoClient({ +import { Currency, MinmoClient } from "@minmoto/sdk"; + +const minmo = new MinmoClient({ partnerId: process.env.MINMO_PARTNER_ID!, apiKey: process.env.MINMO_API_KEY!, - baseUrl: "https://api.staging.minmo.to/api/v1", }); + +const [quote, stores] = await Promise.all([ + minmo.otc.rates.quote(Currency.BTC, Currency.KES), + minmo.integrations.pay.listStores(), +]); ``` -The constructor produces the Partner-bound SDK interface directly. Calls such -as `account.get()`, `settings.get()`, and `integrations.pay.listStores()` use the -configured Partner without a separate `forPartner()` setup call. +### Subscribe to live changes -## Authentication and security +Domain clients expose typed subscriptions alongside their command and query +methods. With a cursor store, a subscription can resume after reconnecting and +reports when an authoritative resync is required. + +```ts +const subscription = minmo.integrations.pay.events({ + onEvent(event) { + console.log(event.type, event.id); + }, + onError(error) { + console.error("Minmo Pay event stream failed", error.message); + }, +}); + +await subscription.ready; -`@minmoto/sdk` supports only Partner API-key authentication. It sends the key in -the `X-API-Key` request header and does not export bearer-token or token-provider -authentication helpers. +// Close the stream during application shutdown. +await subscription.close(); +``` + +Treat an event as a signal that something changed. When current state matters, +read the corresponding resource again through the SDK. + +## Configuration + +```ts +import { + MINMO_PRODUCTION_BASE_URL, + MinmoClient, + type MinmoClientOptions, +} from "@minmoto/sdk"; + +const options: MinmoClientOptions = { + partnerId: process.env.MINMO_PARTNER_ID!, + apiKey: process.env.MINMO_API_KEY!, + baseUrl: process.env.MINMO_BASE_URL ?? MINMO_PRODUCTION_BASE_URL, +}; + +const minmo = new MinmoClient(options); +``` -Partner API keys are server secrets: +| Option | Required | Description | +| --- | --- | --- | +| `partnerId` | Yes | Partner scope used by Partner-bound resources | +| `apiKey` | Yes | Secret Partner API key sent as `X-API-Key` | +| `baseUrl` | No | Minmo API base URL; defaults to `https://api.minmo.to/api/v1` | -- Do not construct this client in browser code. -- Do not expose the key through `NEXT_PUBLIC_`, `VITE_`, or equivalent public - environment variables. -- Do not log client options, request headers, or API keys. -- Store production keys in a secrets manager and grant only the capabilities - required by the integration. +## Error handling -The Partner ID selects request scope. Authorization remains enforced by the -Minmo API; selecting a Partner never grants access to it. +The SDK exposes typed errors so your service can distinguish authentication, +authorization, rate-limit, transport, and other API failures. -## Upstream implementation +```ts +import { MinmoSdkError } from "@minmoto/sdk"; + +try { + await minmo.integrations.pay.listStores(); +} catch (error) { + if (error instanceof MinmoSdkError) { + console.error({ + code: error.code, + status: error.status, + requestId: error.requestId, + retryable: error.retryable, + }); + } + + throw error; +} +``` -The SDK implementation and shared contracts are built in the private -`minmoto/mini` repository. This repository vendors an immutable build artifact -under `vendor/upstream` and publishes only the constrained facade in `dist`. +Use `retryable` as an input to your retry policy, not as permission to retry +without limits. Apply bounded backoff and preserve idempotency keys for +money-moving commands. + +## Authentication and security -`vendor/upstream/manifest.json` records the exact Mini commit and a SHA-256 -checksum covering every vendored file. CI verifies the checksum, ensures the -public output has no private package imports, installs the packed tarball into -an empty consumer, and confirms that private authentication providers are not -exported. +`@minmoto/sdk` supports only Partner API-key authentication. It does not export +bearer-token or token-provider authentication helpers. -To update from a clean, built Mini worktree: +- Construct the client only in trusted server code. +- Never place the API key in `NEXT_PUBLIC_`, `VITE_`, or an equivalent public + environment variable. +- Do not log client options, request headers, API keys, or sensitive response + bodies. +- Grant each key only the capabilities its integration needs, and rotate or + revoke keys according to your operational policy. +- Keep idempotency keys stable when retrying commands that can move money or + create payable resources. + +The Partner ID selects request scope; it does not grant access. The Minmo API +continues to enforce the API key's Partner access and capability policy for +every request. + +## Contributing + +The public SDK is built from a pinned Minmo SDK artifact. CI verifies its +checksum, public export boundary, generated declarations, and packed consumer +experience. ```sh -npm run vendor:upstream -- --worktree /path/to/clean/mini-worktree +npm install npm run check npm run test:package npm pack --dry-run ``` -Never vendor from a dirty worktree or publish `dist` from a different revision -than the one recorded in the upstream manifest. - -## Contributing and releasing +See [`AGENTS.md`](./AGENTS.md) for contributor guidance and +[`RELEASING.md`](./RELEASING.md) for the release process. Bugs and feature +requests are welcome in [GitHub Issues](https://github.com/minmoto/sdk/issues). -Contributor instructions are in [`AGENTS.md`](./AGENTS.md). The repository uses -Conventional Commits, Release Please, semantic versioning, and npm trusted -publishing with provenance. See [`RELEASING.md`](./RELEASING.md) for the release -and one-time registry setup. +## License -The package is MIT-licensed; see [`LICENSE`](./LICENSE). +MIT © Minmo. See [`LICENSE`](./LICENSE).