SettleMint
API referenceTypeScript SDK

The Effect surface

The same namespaced route tree returning Effect values instead of promises, with a tagged failure channel and interruption wired to the request.

Overview

The Effect entry returns typed effects for Platform API calls. Each call has a DalpRequestError failure channel, and fiber interruption aborts a request that uses the client-provided signal.

The route tree and transport match the promise client. Calls return Effect<A, DalpRequestError> instead of Promise<A>.

import { createDalpEffectClient } from "@settlemint/dalp-sdk/effect";
import * as Effect from "effect/Effect";

const dalp = createDalpEffectClient({
  baseUrl: process.env.DALP_API_URL!,
  apiKey: process.env.DALP_API_KEY!,
  runtime: "server",
});

const program = Effect.gen(function* () {
  const tokens = yield* dalp.api.token.list({ page: { limit: 50 } });
  return tokens.data;
});

effect is an optional peer dependency. Install it only if you use this entry.

npm install effect

Why it is a separate entry

The root package does not import Effect. Import @settlemint/dalp-sdk/effect when your application uses Effect.

Both clients use the same route table and transport.

The failure channel

Every call fails with one type, DalpRequestError, carrying the platform's error contract:

const program = dalp.api.token
  .list({ page: { limit: 50 } })
  .pipe(Effect.retry({ times: 3, while: (error) => error.retryable }));
FieldWhat it holds
_tag"DalpRequestError", so Effect.catchTag matches it by tag.
idThe stable DALP identifier when the platform supplied one, otherwise the SDK's own code.
statusThe HTTP status, when there was a response.
retryableWhether retrying this exact request can succeed.
retryAfterSecondsHow long the platform asked you to wait, from Retry-After, when it named a delay.
routeIdWhich route failed, which matters when several are composed in one program.

The same error type covers route failures. Branch on error.id for domain handling and on error.retryable for retry policy. Response types are compile-time only.

Interruption

Interrupting a fiber aborts the request. The abort controller is wired to the fiber rather than handed to you, so a cancelled fiber does not leave a socket open:

import * as Fiber from "effect/Fiber";

const program = Effect.gen(function* () {
  const fiber = yield* Effect.forkChild(dalp.api.token.list({ page: { limit: 50 } }));
  yield* Effect.sleep("2 seconds");
  yield* Fiber.interrupt(fiber); // the HTTP request is aborted
});

A promise wrapper must pass Effect's abort signal into the HTTP request to cancel it. The SDK Effect client creates and connects that signal for you. If you pass your own signal, manage its cancellation yourself.

Composition

Concurrency, retry, and timeout are Effect's, not the SDK's:

const program = Effect.gen(function* () {
  const [tokens, users] = yield* Effect.all(
    [dalp.api.token.list({ page: { limit: 50 } }), dalp.api.party.users.list({ page: { limit: 50 } })],
    {
      concurrency: 2,
    }
  );
  return { tokens: tokens.data, users: users.data };
});
dalp.api.token.list({ page: { limit: 50 } }).pipe(Effect.timeout("5 seconds"), Effect.retry({ times: 3 }));

An Effect.timeout around a call interrupts it, which aborts the request. That composes correctly with settlement: a queue-backed write interrupted mid-wait stops waiting, and the instruction it submitted stays live on the platform exactly as it would if the platform's own wait had run out and answered with a 202 handle. Interrupting the wait is not cancelling the transaction.

Route ids

Dispatch by id, for code that builds its own command surface:

const program = dalp.execute("token/list", { page: { limit: 50 } });

An unknown id fails with a DalpRequestError in the error channel rather than throwing, so the failure stays in the type system with every other failure.

What is the same

Everything below the channel. The flat argument split, the response envelope, conditional reads, settlement, the acting-context headers, and the per-call options are identical, and each is documented once on the pages that cover the promise surface. The only difference is what the call hands back.

Next

Command-line access to the same routes: CLI.

On this page