Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
16d8041
feat(sdk-outpost): establish package and validated deployment model
joshglogau Jul 31, 2026
7c67510
feat(sdk-outpost): add verified sim2 artifacts and generated chain types
joshglogau Jul 31, 2026
ba75407
feat(sdk-outpost): verify deployments through typed chain clients
joshglogau Jul 31, 2026
6b43c8f
chore(sdk-outpost): constrain published package contents
joshglogau Jul 31, 2026
3d98035
feat(sdk-outpost): version sim2 deployments and automate artifact ref…
joshglogau Aug 3, 2026
f5a997f
test(sdk-outpost): verify historical and current deployment compatibi…
joshglogau Aug 3, 2026
4c3bd37
docs(sdk-outpost): document repeatable deployment refreshes and Hub b…
joshglogau Aug 3, 2026
8dd095d
docs(sdk-outpost): clarify clean package boundaries
joshglogau Aug 3, 2026
23bcadf
refactor(sdk-outpost): key deployment assets by Wire chain identity
joshglogau Aug 3, 2026
9c8de46
build(sdk-outpost): gate reproducible npm releases
joshglogau Aug 3, 2026
54ef04e
docs(sdk-outpost): document first public release
joshglogau Aug 3, 2026
c389a21
refactor(sdk-outpost): consume source-owned artifacts
joshglogau Aug 4, 2026
e126e15
Link source-owned outpost artifacts in platform builds
joshglogau Aug 4, 2026
a20ea7b
Narrow local artifact linking to pnpm
joshglogau Aug 4, 2026
3589750
Narrow sdk-outpost integration scope
joshglogau Aug 4, 2026
601be0a
Keep root publishing documentation unchanged
joshglogau Aug 4, 2026
03f1ad8
build: link local outpost artifact outputs
joshglogau Aug 4, 2026
69087c4
feat(sdk-outpost): verify immutable deployment profiles
joshglogau Aug 5, 2026
d2e498e
feat(sdk-outpost): add reserve swap workflows
joshglogau Aug 5, 2026
2f819d7
fix: align Solana reserve swaps with deployed outpost
joshglogau Aug 7, 2026
c663fea
fix: add gas headroom to Ethereum reserve swaps
joshglogau Aug 7, 2026
a032e8a
fix(sdk-outpost): preserve Solana account namespace types
joshglogau Aug 7, 2026
4632308
docs(sdk-outpost): clarify first-release gates
joshglogau Aug 11, 2026
2041e1a
fix(sdk-outpost): bind clients to producer runtimes
joshglogau Aug 11, 2026
d1f35f8
feat(sdk-core): match reserve pairs atomically
joshglogau Aug 7, 2026
56d972d
feat(sdk-outpost): add private reserve lifecycle
joshglogau Aug 7, 2026
3da08a7
fix(sdk-outpost): harden reserve creation preflight
joshglogau Aug 7, 2026
12b986c
feat(sdk-outpost): support exact deployment bundles
joshglogau Aug 13, 2026
a83df18
build(sdk-outpost): preserve local producer linking
joshglogau Aug 13, 2026
2bb981d
fix(sdk-core): preserve root type resolution
joshglogau Aug 13, 2026
5939c1d
build(sdk-outpost): consume published artifacts
joshglogau Aug 14, 2026
21b358b
ci(release): enforce frozen publish inputs
joshglogau Aug 14, 2026
6887c70
chore(sdk-outpost): align package boundaries with platform rules
joshglogau Aug 14, 2026
8a3111f
refactor(sdk-outpost): use npm artifacts exclusively
joshglogau Aug 14, 2026
d82ec62
Merge remote-tracking branch 'origin/master' into feature/sdk-outpost
joshglogau Aug 18, 2026
be4645e
Merge remote-tracking branch 'origin/master' into feature/sdk-outpost
joshglogau Aug 18, 2026
9b0990c
chore(sdk-outpost): consume current producer artifacts
joshglogau Aug 18, 2026
ee53164
fix(sdk-outpost): address review feedback
joshglogau Aug 18, 2026
db20537
fix(sdk-outpost): address release review feedback
joshglogau Aug 19, 2026
84c99db
refactor(sdk-outpost): consume producer libraries with ethers v6
joshglogau Aug 19, 2026
1c31533
fix(sdk-outpost): normalize Ethereum runtime immutables
joshglogau Aug 20, 2026
579e213
fix(sdk-outpost): align artifact dependencies
joshglogau Aug 21, 2026
7235f7a
feat(sdk-outpost): add Ethereum node owners
joshglogau Aug 18, 2026
6cf288c
fix(sdk-outpost): keep BAR capability optional
joshglogau Aug 18, 2026
f2cafe2
refactor(sdk-outpost): align node owners with ethers v6
joshglogau Aug 21, 2026
cb1dc3a
Merge pull request #71 from Wire-Network/feature/sdk-outpost-node-owner
joshglogau Aug 21, 2026
43ccc5d
docs(sdk-outpost): align deployment artifact handoff
joshglogau Aug 21, 2026
7accbd7
Merge remote-tracking branch 'origin/master' into feature/sdk-outpost
joshglogau Aug 27, 2026
1eca214
feat(sdk-outpost): register verified artifact suite
joshglogau Aug 27, 2026
b4cb1ec
fix(sdk-outpost): restore platform artifact links
joshglogau Aug 27, 2026
8b8f461
docs(sdk-outpost): narrow local link guidance
joshglogau Aug 28, 2026
d08bf13
Don't add duplicate code paths whenever possible
jglanz Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ yarn-error.log*

# JUnit test-result output (CI artifact)
/reports/
/junit.xml

# oh-my-claudecode runtime state (operational artifacts, never committed)
.omc/
30 changes: 16 additions & 14 deletions .pnpmfile.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* pnpm hook to resolve @wireio packages from the local wire-libraries-ts monorepo.
*
* Usage:
* 1. Add packages you want to link to the `localOverrides` map below.
* 2. Run `pnpm install` — pnpm will use these local paths instead of the registry.
* 3. Comment out or remove entries to revert to registry versions.
* 1. Build any supported sibling package outputs you want to use locally.
* 2. Run `pnpm install --lockfile=false` to consume available local packages.
* 3. Remove those outputs to resolve packages from the registry again.
*
* Docs: https://pnpm.io/pnpmfile
*/
Expand All @@ -28,30 +28,32 @@ function isDirectory(dirPath) {
}
}

/**
* Map of package names to their local directory in wire-libraries-ts.
* Uncomment the entries you want to link locally.
*/
/** Map of locally available packages keyed by package name. */
const localOverrides = {}

// AS THE PROTOBUF LIBS HAVE BEEN RELOCATED TO SYSIO
// WE CAN NOW USE THE MODELS WITHOUT ISSUE.
// CIRCULAR DEP REMOVED

const wireOPPPkgPaths = ["typescript", "solidity"].map(target => [
`@wireio/opp-${target}-models`,
Path.resolve(__dirname, "..", "wire-sysio", "build", "opp", target)
])
const wirePkgPaths = [
...["typescript", "solidity"].map(target => [
`@wireio/opp-${target}-models`,
Path.resolve(__dirname, "..", "wire-sysio", "build", "opp", target)
]),
...["ethereum","solana"].map(target => [
`@wireio/outpost-${target}-artifacts`,
Path.resolve(__dirname, "..", `wire-${target}`, "build", "sdk-artifacts")
])
]

wireOPPPkgPaths
wirePkgPaths
.filter(([, path]) => isDirectory(path))
.forEach(([pkgName, path]) => {
localOverrides[pkgName] = path
})

/**
* `readPackage` hook, which links locally available versions of
* shared libraries and models.
* `readPackage` hook, which links locally available packages.
*
* @param pkg
* @param context
Expand Down
37 changes: 27 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
## Build & Development

```bash
pnpm install # Install registry deps (pnpm 10.34.5, Node >=22)
# Link local OPP models from wire-sysio:
WIRE_LINK_LOCAL_OPP_MODELS=1 pnpm install --lockfile=false
pnpm install # Install deps (pnpm 10.34.5, Node >=22); available sibling OPP models link automatically
pnpm build # Build all packages via tsc -b
pnpm build:dev # Watch mode (incremental)
pnpm test # Build + jest (all packages)
Expand Down Expand Up @@ -36,6 +34,7 @@ pnpm workspaces with TypeScript composite project references. No Lerna/Nx.
| `@wireio/shared-web` | Web-specific utilities | No | ESM |
| `@wireio/shared-node` | Node.js utilities | Yes | Hybrid ESM+CJS |
| `@wireio/sdk-core` | Wire blockchain SDK types/primitives | Yes | Hybrid ESM+CJS |
| `@wireio/sdk-outpost` | Typed, verified external-chain outpost clients | No — first release pending | Hybrid ESM+CJS |
| `@wireio/wallet-ext-sdk` | Wallet extension client SDK | Yes | ESM |
| `@wireio/wallet-browser-ext` | Chrome extension developer wallet | No | Webpack bundle |

Expand All @@ -46,6 +45,8 @@ shared ──→ shared-web
──→ shared-node

sdk-core ──→ wallet-ext-sdk ──→ wallet-browser-ext

source artifact libraries ──→ sdk-outpost external-chain clients
```

Protoc plugins and bundler are standalone (no internal deps).
Expand All @@ -68,7 +69,7 @@ Root `tsconfig.json` has project references to all packages. Build order is reso

## Hybrid ESM/CJS Build Pattern

Packages that publish both ESM and CJS (`shared`, `sdk-core`, `shared-node`) use:
Packages that publish both ESM and CJS (`shared`, `sdk-core`, `sdk-outpost`, `shared-node`) use:

1. Two tsconfig files: one for `lib/esm/`, one for `lib/cjs/`
2. Post-build: `scripts/fix-hybrid-output.mjs` patches relative imports with `.js` extensions and creates `lib/cjs/package.json` with `{"type":"commonjs"}`
Expand Down Expand Up @@ -191,12 +192,19 @@ Every new/modified symbol ships unit tests in the same change. Tests never assum

## CI/CD

GitHub Actions (`.github/workflows/publish-npm.yaml`):
- Triggers on push to `master` (skips if `[skip release]` in commit message)
- Bumps all packages patch version (`pnpm -r exec -- pnpm version patch`)
- Auto-commits `chore(release): bump patch [skip release]`
- Publishes all non-private packages to npm with provenance (`pnpm -r publish --access public --provenance`)
- Published package manifests must keep `repository.url` set to `https://github.com/Wire-Network/wire-libraries-ts` so npm provenance matches GitHub Actions source metadata.
GitHub Actions uses a two-gate release flow:
- `prepare-release.yaml` is manually dispatched with a bump type. It bumps each
package on its own version track and opens a release-preparation PR; it never
pushes directly to `master` or publishes.
- After that PR is reviewed and merged, `tag-release.yaml` is manually
dispatched and pauses for approval in the `release` environment.
- The approved job installs the workspace, builds and tests, publishes all
non-private packages in dependency order, creates the annotated tag, and
creates the GitHub release.
- `workspace:*` dependencies become concrete current workspace versions at
publish time. Published package manifests must keep `repository.url` set to
`https://github.com/Wire-Network/wire-libraries-ts` so npm provenance matches
GitHub Actions source metadata.

## Documentation Comments

Expand All @@ -216,6 +224,15 @@ All generated or modified code **must** include JSDoc comments (`/** ... */`), c
- System-contract `prepare` prefers synchronous ABI encoding but must retain a typed `AnyAction` fallback so `APIClient` can resolve the deployed ABI. Never invent a default write authorization in the public SDK.
- `packages/sdk-core/src/contracts/sysio/reserv` owns public `sysio.reserv` registry reads, normalized rows, matching, rewards, and read-only quote helpers. External-chain reserve custody belongs in the ABI/IDL-owning chain SDK.
- `packages/sdk-core/src/contracts/sysio/uwrit` preserves raw request bytes and exposes `sourceRequestId` for swap correlation. External outpost ids are big-endian; synthetic WIRE queue ids are little-endian and high-bit tagged.
- `packages/sdk-outpost` owns typed Ethereum/Solana clients and validates caller-supplied immutable deployment profiles. Canonical ABIs, IDLs, runtime templates, program binaries, ethers v6 factories, and Anchor types come from exact packages owned by `wire-ethereum` and `wire-solana`. For local platform development, the root pnpm hook links available sibling artifact outputs; never commit `file:`/`link:` specs to package manifests or the lockfile.
- Producer repositories assemble those npm packages from checksummed deployment handoffs. `sdk-outpost` never downloads the handoff or owns producer publication inputs.
- `sdk-outpost` registers exact producer package pairs in an internal compile-time artifact-suite registry. Select suites from deployment-profile ABI/IDL identity and verify exact live runtime identity; never key suite selection by environment names or turn it into an endpoint catalog/runtime package loader.
- `OutpostClient.create` is sdk-outpost's only published client-construction facade. It delegates family selection to an internal factory; concrete Ethereum/Solana instance types remain available for typing, but their backend factories and module paths are not package entrypoints.
- `packages/sdk-outpost` owns external reserve lifecycle, swap execution, and BAR-backed Ethereum node-owner registration. BAR is an optional deployment capability: profiles without it preserve reserve and swap behavior, while node-owner access fails closed. Node-owner registration must use BAR's canonical WireNodes address and is not staking; staking remains outside this package until its dedicated migration.
- `sdk-outpost` accepts caller-owned providers and deployment profiles, verifies exact Ethereum implementations and Solana ProgramData against source-owned runtime artifacts, and never owns mutable endpoint catalogs. A same-code cluster respin requires a new profile, not an artifact or SDK release; any deployable binary change requires both a producer artifact and SDK release.
- A connected outpost client proves deployment compatibility, not swap or stake readiness. Wire-chain orchestration remains in `sdk-core`, and consumers must retain flow-specific capability gates.
- Publish `sdk-outpost` only through the repository release workflow after its normal build and tests pass.
- Do not describe `sdk-outpost` as npm-available until `npm view` succeeds for both exact producer artifact versions and `@wireio/sdk-outpost`, and a clean platform-compatible install passes without sibling artifact links.
- `wallet-browser-ext` uses a global shim to avoid `new Function()` restrictions in Chrome MV3
- Path aliases in tsconfig base resolve to `src/` for dev, but published packages use `lib/` — jest module name maps handle this mismatch
- Node >=22 required (package.json says >=22, README says >=24 — actual CI uses v24)
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@ A monorepo containing shared TypeScript libraries for Wire applications, providi
| [`@wireio/shared-web`](packages/shared-web/) | Web-specific utilities | *private* |
| [`@wireio/shared-node`](packages/shared-node/) | Node.js-specific utilities | *private* |
| [`@wireio/sdk-core`](packages/sdk-core/) | Wire blockchain SDK core types, primitives, signing helpers, generated `sysio` contract proxy, and domain workflows such as multisig and reserves | [![npm](https://img.shields.io/npm/v/@wireio/sdk-core)](https://www.npmjs.com/package/@wireio/sdk-core) |
| [`@wireio/sdk-outpost`](packages/sdk-outpost/) | Strictly typed Ethereum and Solana outpost clients consuming source-owned artifact libraries | *first release pending* |
| [`@wireio/wallet-ext-sdk`](packages/wallet-ext-sdk/) | Client SDK for the Wire Wallet browser extension | [![npm](https://img.shields.io/npm/v/@wireio/wallet-ext-sdk)](https://www.npmjs.com/package/@wireio/wallet-ext-sdk) |
| [`@wireio/wallet-browser-ext`](packages/wallet-browser-ext/) | Chrome extension developer wallet for Wire | *private* |

The sdk-outpost package consumes exact published versions of the Ethereum and
Solana artifact libraries, including their ethers v6 factories and Anchor
types. Chain bindings are generated and verified by those producer repos, not
inside this monorepo. An internal compile-time artifact-suite registry selects
compatible producer bindings from caller-supplied deployment profiles without
owning endpoints or environment configuration.

## Examples

| Example | Description |
Expand All @@ -30,9 +38,6 @@ A monorepo containing shared TypeScript libraries for Wire applications, providi
# Install dependencies
pnpm install

# Install with locally generated OPP models from wire-sysio
WIRE_LINK_LOCAL_OPP_MODELS=1 pnpm install --lockfile=false

# Build all packages
pnpm build

Expand All @@ -56,6 +61,7 @@ wire-libraries-ts/
│ ├── shared-web/ # Web-specific utilities
│ ├── shared-node/ # Node.js-specific utilities
│ ├── sdk-core/ # Wire blockchain SDK core
│ ├── sdk-outpost/ # Typed external-chain outpost SDK
│ ├── wallet-ext-sdk/ # Wallet extension client SDK
│ ├── wallet-browser-ext/ # Chrome extension wallet
│ ├── protoc-gen-solana/ # protoc plugin → Rust/Solana
Expand Down
116 changes: 116 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Releasing `@wireio/sdk-outpost`

`@wireio/sdk-outpost` participates in the same repository-wide release as
`@wireio/sdk-core`. Do not manually change its version or publish a workspace
directory outside this process.

## Current first-release state

Ethereum and Solana producer packages `0.3.0` are the exact prerequisites for
the first SDK release. Both are publicly installable and provide directly
importable TypeScript libraries, ethers v6 factories, Anchor types, manifests,
and runtime artifacts. The first `@wireio/sdk-outpost` release remains pending
platform review. Its workspace version remains `0.0.0` until the existing
repository-wide patch workflow bumps and publishes it.

## Artifact prerequisites

The package consumes exact runtime versions of:

- `@wireio/outpost-ethereum-artifacts`, published from `wire-ethereum`;
- `@wireio/outpost-solana-artifacts`, published from `wire-solana`.

Publish a new producer package when its ABI/IDL or deployable contract/program
binary changes. Publish `sdk-outpost` when its public behavior changes or a new
ABI, IDL, normalized Ethereum runtime, or Solana program binary must be compiled
into deployment verification. A same-code deployment respin, address change, or
endpoint rotation does not require either package to be republished; emit a new
immutable deployment profile for a respin and update the separate endpoint
catalog for mutable endpoints.

Before updating either dependency, verify its registry integrity/signature,
source revision, artifact checksums, and immutable version. The producer repos
are non-public, so their current npm releases do not carry public provenance.
Keep both versions exact in `packages/sdk-outpost/package.json`. Update
`pnpm-lock.yaml` with the repository-pinned pnpm version only after both exact
versions resolve from npm, then run the repository install and test flow.

## Release requirements

- Use Node.js 24 and the repository-pinned pnpm version through Corepack.
- Import ethers v6 factories, Anchor types, runtime artifacts, and manifests
directly from the exact producer packages; `sdk-outpost` must not regenerate
or duplicate them.
- Confirm the package contains no secrets, RPC credentials, private keys,
deployment addresses, or mutable environment configuration.
- Confirm deployment profiles are distributed through the authenticated
platform release channel; their schema and checksum-derived IDs are not
signatures.
- Keep `repository.url` exactly equal to
`https://github.com/Wire-Network/wire-libraries-ts` for npm provenance.

Local checkouts are verification environments, not publishing authorities. Run
the checks there, but let the protected GitHub Actions workflow create the
release.

## Before merge

From the repository root:

```sh
corepack pnpm install --no-frozen-lockfile --ignore-scripts
corepack pnpm run lint
corepack pnpm run test:ci
corepack pnpm --dir packages/sdk-outpost run build
```

Package verification requires the publishable files to remain limited to the
README and CJS/ESM build outputs. Raw producer packages and generated source
trees must not be published by `sdk-outpost`.

## First npm listing

The first successful publish creates the npm package page. Release sequence:

1. Confirm both exact `0.3.0` producer artifact versions are publicly
installable.
2. Confirm the `wireio` organization exists on npm and the release owner can
publish public packages in that scope.
3. Confirm npm two-factor authentication is enabled for the release owner.
4. Confirm the GitHub repository secret `NPM_TOKEN` can publish to the `wireio`
organization under its required authentication policy.
5. Confirm the GitHub `release` environment exists with required reviewers; the
environment approval is the second release gate.
6. Merge the reviewed feature pull request into `master`.
7. Dispatch **Prepare Release** with the intended bump, approve its checks, and
merge the generated version-bump pull request.
8. Dispatch **Tag Release** and approve the `release` environment gate.

The preparation gate keeps each package on its existing version track. A patch
bump therefore makes the first SDK release `@wireio/sdk-outpost@0.0.1`, while
`@wireio/sdk-core` advances by one patch on its independent track.
The Tag Release gate must install the workspace, build and test every package,
and publish with npm provenance.

Do not create the first `sdk-outpost` version manually. A failed publish must be
corrected in source and released as the next patch; published npm versions are
immutable.

## After the first publication

Verify the listing and install path:

```sh
npm view @wireio/sdk-outpost version dist-tags repository --json
npm install @wireio/sdk-outpost
```

Then configure npm trusted publishing for `tag-release.yaml`. After a trusted
publish succeeds, remove the long-lived write token from the publish step and
restrict token-based publishing in npm package settings. Keep `id-token: write`
so npm can generate provenance.

References:

- <https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/>
- <https://docs.npmjs.com/trusted-publishers/>
6 changes: 6 additions & 0 deletions etc/tsconfig/tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
"@wireio/sdk-core/*": [
"./packages/sdk-core/src/*"
],
"@wireio/sdk-outpost": [
"./packages/sdk-outpost/src"
],
"@wireio/sdk-outpost/*": [
"./packages/sdk-outpost/src/*"
],
"@wireio/wallet-ext-sdk": [
"./packages/wallet-ext-sdk/src"
],
Expand Down
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const config: Config = {
"packages/shared-node",
"packages/shared-web",
"packages/sdk-core",
"packages/sdk-outpost",
"packages/wallet-browser-ext",
"packages/wallet-ext-sdk"
]
Expand Down
15 changes: 15 additions & 0 deletions packages/sdk-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,23 @@ await reserves.pushMatchReserve({
matcher: "alice",
wireAmount: pending[0].requestedWireAmount
})

// Several pending rows can be activated atomically in one signed transaction.
await reserves.pushMatchReserves({
matches: pending.map(reserve => ({
chainCode: reserve.chainCode,
tokenCode: reserve.tokenCode,
reserveCode: reserve.reserveCode,
matcher: "alice",
wireAmount: reserve.requestedWireAmount
}))
})
```

`pushMatchReserves` preserves the supplied action order and rejects an empty
match list. The Wire transaction is atomic: either every `matchreserve` action
is accepted or none is applied.

## Reserve swaps

Reserve swap integrations compose three on-chain sources instead of carrying a
Expand Down
Loading
Loading