@dominusnode/sdk 1.1.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,45 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.X402Resource = void 0;
3
+ exports.X402Resource = exports.X402_HEADERS = exports.X402_PROTOCOL_VERSION = void 0;
4
4
  /**
5
- * x402 (HTTP 402 Payment Required) protocol information.
5
+ * x402 V2 protocol version.
6
+ * V2 uses CAIP-2 network identifiers (e.g. "eip155:8453" instead of "base").
7
+ */
8
+ exports.X402_PROTOCOL_VERSION = "2";
9
+ /**
10
+ * x402 V2 header constants.
11
+ * V2 renamed the payment headers. Servers should accept both old and new
12
+ * for backward compatibility during the transition period.
13
+ */
14
+ exports.X402_HEADERS = {
15
+ /** V2 payment header (replaces V1 "X-PAYMENT"). */
16
+ PAYMENT_SIGNATURE: "PAYMENT-SIGNATURE",
17
+ /** V1 legacy payment header — kept for backward compatibility. */
18
+ PAYMENT_SIGNATURE_LEGACY: "X-PAYMENT",
19
+ /** V2 payment response header (replaces V1 "X-PAYMENT-RESPONSE"). */
20
+ PAYMENT_RESPONSE: "PAYMENT-RESPONSE",
21
+ /** V1 legacy payment response header. */
22
+ PAYMENT_RESPONSE_LEGACY: "X-PAYMENT-RESPONSE",
23
+ /** V2 payment requirements header. */
24
+ PAYMENT_REQUIRED: "PAYMENT-REQUIRED",
25
+ };
26
+ /**
27
+ * x402 V2 (HTTP 402 Payment Required) protocol information.
6
28
  *
7
29
  * Provides details about x402 micropayment support, facilitator addresses,
8
- * pricing, and supported chains/currencies for AI agent payments.
30
+ * pricing, supported chains/currencies, and payment schemes for AI agent
31
+ * payments.
32
+ *
33
+ * V2 changes from V1:
34
+ * - Protocol version "2" (was "1")
35
+ * - CAIP-2 network IDs (e.g. "eip155:8453" instead of "base")
36
+ * - Payment header: PAYMENT-SIGNATURE (was X-PAYMENT)
37
+ * - Response header: PAYMENT-RESPONSE (was X-PAYMENT-RESPONSE)
38
+ * - Requirements header: PAYMENT-REQUIRED
39
+ * - New token: EURC (in addition to USDC)
40
+ * - New scheme: permit2 (in addition to exact)
41
+ * - Additional facilitator chains: Ethereum (eip155:1), Optimism (eip155:10),
42
+ * Arbitrum (eip155:42161), and Solana
9
43
  */
10
44
  class X402Resource {
11
45
  http;
@@ -13,8 +47,8 @@ class X402Resource {
13
47
  this.http = http;
14
48
  }
15
49
  /**
16
- * Get x402 protocol information including facilitator details,
17
- * pricing, supported chains, and currencies.
50
+ * Get x402 V2 protocol information including facilitator details,
51
+ * pricing, supported chains, currencies, and payment schemes.
18
52
  *
19
53
  * This endpoint does not require authentication.
20
54
  */
@@ -22,14 +22,18 @@ class WalletResource {
22
22
  }
23
23
  /** Create a Stripe checkout session for wallet top-up. */
24
24
  async topUpStripe(amountCents) {
25
- if (!Number.isInteger(amountCents) || amountCents <= 0 || amountCents > 2_147_483_647) {
25
+ if (!Number.isInteger(amountCents) ||
26
+ amountCents <= 0 ||
27
+ amountCents > 2_147_483_647) {
26
28
  throw new Error("amountCents must be a positive integer <= 2,147,483,647");
27
29
  }
28
30
  return this.http.post("/api/wallet/topup/stripe", { amountCents });
29
31
  }
30
32
  /** Create a crypto invoice for wallet top-up. Minimum $10 (1000 cents). */
31
33
  async topUpCrypto(amountCents, currency) {
32
- if (!Number.isInteger(amountCents) || amountCents <= 0 || amountCents > 2_147_483_647) {
34
+ if (!Number.isInteger(amountCents) ||
35
+ amountCents <= 0 ||
36
+ amountCents > 2_147_483_647) {
33
37
  throw new Error("amountCents must be a positive integer <= 2,147,483,647");
34
38
  }
35
39
  if (amountCents < 1000) {
@@ -40,7 +44,9 @@ class WalletResource {
40
44
  }
41
45
  /** Create a PayPal order for wallet top-up. Minimum $5 (500 cents). */
42
46
  async topUpPaypal(amountCents) {
43
- if (!Number.isInteger(amountCents) || amountCents <= 0 || amountCents > 2_147_483_647) {
47
+ if (!Number.isInteger(amountCents) ||
48
+ amountCents <= 0 ||
49
+ amountCents > 2_147_483_647) {
44
50
  throw new Error("amountCents must be a positive integer <= 2,147,483,647");
45
51
  }
46
52
  if (amountCents < 500) {
@@ -3,6 +3,7 @@ import type { User, LoginResult, MfaStatus, MfaSetup } from "./types.js";
3
3
  export declare class AuthResource {
4
4
  private http;
5
5
  constructor(http: HttpClient);
6
+ private solvePoW;
6
7
  register(email: string, password: string): Promise<{
7
8
  user: User;
8
9
  token?: string;
package/dist/esm/auth.js CHANGED
@@ -1,10 +1,54 @@
1
+ import * as crypto from "node:crypto";
2
+ const POW_MAX_NONCE = 100_000_000;
3
+ function countLeadingZeroBits(hash) {
4
+ let count = 0;
5
+ for (const byte of hash) {
6
+ if (byte === 0) {
7
+ count += 8;
8
+ }
9
+ else {
10
+ let mask = 0x80;
11
+ while (mask && !(byte & mask)) {
12
+ count += 1;
13
+ mask >>= 1;
14
+ }
15
+ break;
16
+ }
17
+ }
18
+ return count;
19
+ }
1
20
  export class AuthResource {
2
21
  http;
3
22
  constructor(http) {
4
23
  this.http = http;
5
24
  }
25
+ async solvePoW() {
26
+ try {
27
+ const challenge = await this.http.post("/api/auth/pow/challenge", {}, false);
28
+ const { challengeId, prefix } = challenge;
29
+ const difficulty = Math.min(challenge.difficulty, 32);
30
+ for (let nonce = 0; nonce < POW_MAX_NONCE; nonce++) {
31
+ const hash = crypto
32
+ .createHash("sha256")
33
+ .update(prefix + nonce)
34
+ .digest();
35
+ if (countLeadingZeroBits(hash) >= difficulty) {
36
+ return { challengeId, nonce };
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
6
45
  async register(email, password) {
7
- return this.http.post("/api/auth/register", { email, password }, false);
46
+ const pow = await this.solvePoW();
47
+ const body = { email, password };
48
+ if (pow) {
49
+ body.pow = pow;
50
+ }
51
+ return this.http.post("/api/auth/register", body, false);
8
52
  }
9
53
  async login(email, password) {
10
54
  return this.http.post("/api/auth/login", { email, password }, false);
@@ -22,7 +66,10 @@ export class AuthResource {
22
66
  return this.http.get("/api/auth/me");
23
67
  }
24
68
  async changePassword(currentPassword, newPassword) {
25
- await this.http.post("/api/auth/change-password", { currentPassword, newPassword });
69
+ await this.http.post("/api/auth/change-password", {
70
+ currentPassword,
71
+ newPassword,
72
+ });
26
73
  }
27
74
  async verifyKey(apiKey) {
28
75
  return this.http.post("/api/auth/verify-key", { apiKey }, false);
@@ -11,6 +11,7 @@ import { AgenticWalletResource } from "./resources/agent-wallet.js";
11
11
  import { TeamsResource } from "./resources/teams.js";
12
12
  import { X402Resource } from "./resources/x402.js";
13
13
  import { WalletAuthResource } from "./resources/wallet-auth.js";
14
+ import { MppResource } from "./resources/mpp.js";
14
15
  import type { DominusNodeConfig, LoginResult } from "./types.js";
15
16
  export declare class DominusNodeClient {
16
17
  readonly auth: AuthResource;
@@ -26,6 +27,7 @@ export declare class DominusNodeClient {
26
27
  readonly teams: TeamsResource;
27
28
  readonly x402: X402Resource;
28
29
  readonly walletAuth: WalletAuthResource;
30
+ readonly mpp: MppResource;
29
31
  private tokenManager;
30
32
  private http;
31
33
  private apiKey;
@@ -13,6 +13,7 @@ import { AgenticWalletResource } from "./resources/agent-wallet.js";
13
13
  import { TeamsResource } from "./resources/teams.js";
14
14
  import { X402Resource } from "./resources/x402.js";
15
15
  import { WalletAuthResource } from "./resources/wallet-auth.js";
16
+ import { MppResource } from "./resources/mpp.js";
16
17
  import { DEFAULT_BASE_URL } from "./constants.js";
17
18
  export class DominusNodeClient {
18
19
  auth;
@@ -28,6 +29,7 @@ export class DominusNodeClient {
28
29
  teams;
29
30
  x402;
30
31
  walletAuth;
32
+ mpp;
31
33
  tokenManager;
32
34
  http;
33
35
  apiKey = null;
@@ -50,6 +52,7 @@ export class DominusNodeClient {
50
52
  this.teams = new TeamsResource(this.http);
51
53
  this.x402 = new X402Resource(this.http);
52
54
  this.walletAuth = new WalletAuthResource(this.http, this.tokenManager);
55
+ this.mpp = new MppResource(this.http);
53
56
  // Set refresh function AFTER auth is initialized
54
57
  this.tokenManager.setRefreshFunction(async (rt) => {
55
58
  const res = await this.auth.refresh(rt);
package/dist/esm/http.js CHANGED
@@ -45,12 +45,18 @@ function throwForStatus(status, body, headers) {
45
45
  if (message.length > 500)
46
46
  message = message.slice(0, 500) + "... [truncated]";
47
47
  switch (status) {
48
- case 400: throw new ValidationError(message);
49
- case 401: throw new AuthenticationError(message);
50
- case 402: throw new InsufficientBalanceError(message);
51
- case 403: throw new AuthorizationError(message);
52
- case 404: throw new NotFoundError(message);
53
- case 409: throw new ConflictError(message);
48
+ case 400:
49
+ throw new ValidationError(message);
50
+ case 401:
51
+ throw new AuthenticationError(message);
52
+ case 402:
53
+ throw new InsufficientBalanceError(message);
54
+ case 403:
55
+ throw new AuthorizationError(message);
56
+ case 404:
57
+ throw new NotFoundError(message);
58
+ case 409:
59
+ throw new ConflictError(message);
54
60
  case 429: {
55
61
  const parsed = parseInt(headers.get("retry-after") ?? "60", 10);
56
62
  const retryAfter = Number.isFinite(parsed) ? parsed : 60; // NaN guard
@@ -18,10 +18,12 @@ export { AgenticWalletResource } from "./resources/agent-wallet.js";
18
18
  export type { AgenticWallet, AgenticWalletTransaction, AgenticWalletListResponse, AgenticWalletFundResponse, AgenticWalletTransactionsResponse, AgenticWalletDeleteResponse, } from "./resources/agent-wallet.js";
19
19
  export { TeamsResource } from "./resources/teams.js";
20
20
  export type { Team, TeamMember, TeamInvite, TeamListResponse, TeamMembersResponse, TeamInvitesResponse, TeamKeysResponse, TeamKeyCreateResponse, TeamDeleteResponse, TeamFundResponse, TeamTransactionsResponse, } from "./resources/teams.js";
21
- export { X402Resource } from "./resources/x402.js";
22
- export type { X402Info, X402Facilitator, X402Pricing, } from "./resources/x402.js";
21
+ export { X402Resource, X402_PROTOCOL_VERSION, X402_HEADERS, } from "./resources/x402.js";
22
+ export type { X402Info, X402Facilitator, X402PaymentHeaders, X402Pricing, X402Scheme, X402Token, } from "./resources/x402.js";
23
23
  export { WalletAuthResource } from "./resources/wallet-auth.js";
24
24
  export type { WalletChallenge, WalletVerifyResult, WalletLinkResult, } from "./resources/wallet-auth.js";
25
+ export { MppResource } from "./resources/mpp.js";
26
+ export type { MppInfo, MppPricing, MppLimits, MppTopUpResponse, MppSessionResponse, MppCloseResponse, MppSessionStatus, MppChallengeResponse, MppCredentialPayload, } from "./resources/mpp.js";
25
27
  export type { DateRangeOptions as AdminDateRangeOptions, ListUsersResponse, GetUserResponse, RevenueResponse, DailyRevenueEntry, DailyRevenueResponse, } from "./admin.js";
26
28
  export { HttpClient } from "./http.js";
27
29
  export type { HttpOptions } from "./http.js";
package/dist/esm/index.js CHANGED
@@ -12,8 +12,9 @@ export { AdminResource } from "./admin.js";
12
12
  export { SlotsResource } from "./slots.js";
13
13
  export { AgenticWalletResource } from "./resources/agent-wallet.js";
14
14
  export { TeamsResource } from "./resources/teams.js";
15
- export { X402Resource } from "./resources/x402.js";
15
+ export { X402Resource, X402_PROTOCOL_VERSION, X402_HEADERS, } from "./resources/x402.js";
16
16
  export { WalletAuthResource } from "./resources/wallet-auth.js";
17
+ export { MppResource } from "./resources/mpp.js";
17
18
  // Infrastructure (HttpClient for advanced custom integrations)
18
19
  export { HttpClient } from "./http.js";
19
20
  // TokenManager is internal — not exported to prevent misuse of token lifecycle
@@ -4,11 +4,16 @@ export class AgenticWalletResource {
4
4
  this.http = http;
5
5
  }
6
6
  async create(label, spendingLimitCents = 10000, options) {
7
- if (!Number.isInteger(spendingLimitCents) || spendingLimitCents < 0 || spendingLimitCents > 2_147_483_647) {
7
+ if (!Number.isInteger(spendingLimitCents) ||
8
+ spendingLimitCents < 0 ||
9
+ spendingLimitCents > 2_147_483_647) {
8
10
  throw new Error("spendingLimitCents must be a non-negative integer <= 2,147,483,647");
9
11
  }
10
- if (options?.dailyLimitCents !== undefined && options.dailyLimitCents !== null) {
11
- if (!Number.isInteger(options.dailyLimitCents) || options.dailyLimitCents < 0 || options.dailyLimitCents > 2_147_483_647) {
12
+ if (options?.dailyLimitCents !== undefined &&
13
+ options.dailyLimitCents !== null) {
14
+ if (!Number.isInteger(options.dailyLimitCents) ||
15
+ options.dailyLimitCents < 0 ||
16
+ options.dailyLimitCents > 2_147_483_647) {
12
17
  throw new Error("dailyLimitCents must be a non-negative integer <= 2,147,483,647");
13
18
  }
14
19
  }
@@ -26,14 +31,19 @@ export class AgenticWalletResource {
26
31
  return this.http.get(`/api/agent-wallet/${encodeURIComponent(walletId)}`);
27
32
  }
28
33
  async fund(walletId, amountCents) {
29
- if (!Number.isInteger(amountCents) || amountCents <= 0 || amountCents > 2_147_483_647) {
34
+ if (!Number.isInteger(amountCents) ||
35
+ amountCents <= 0 ||
36
+ amountCents > 2_147_483_647) {
30
37
  throw new Error("amountCents must be a positive integer <= 2,147,483,647");
31
38
  }
32
39
  return this.http.post(`/api/agent-wallet/${encodeURIComponent(walletId)}/fund`, { amountCents });
33
40
  }
34
41
  async updateWalletPolicy(walletId, policy) {
35
- if (policy.dailyLimitCents !== undefined && policy.dailyLimitCents !== null) {
36
- if (!Number.isInteger(policy.dailyLimitCents) || policy.dailyLimitCents < 0 || policy.dailyLimitCents > 2_147_483_647) {
42
+ if (policy.dailyLimitCents !== undefined &&
43
+ policy.dailyLimitCents !== null) {
44
+ if (!Number.isInteger(policy.dailyLimitCents) ||
45
+ policy.dailyLimitCents < 0 ||
46
+ policy.dailyLimitCents > 2_147_483_647) {
37
47
  throw new Error("dailyLimitCents must be a non-negative integer <= 2,147,483,647");
38
48
  }
39
49
  }
@@ -0,0 +1,161 @@
1
+ import type { HttpClient } from "../http.js";
2
+ /** IETF MPP auth scheme name (official spec) */
3
+ export declare const MPP_AUTH_SCHEME = "Payment";
4
+ /** Legacy auth scheme name (backward compat) */
5
+ export declare const MPP_AUTH_SCHEME_LEGACY = "MPP";
6
+ export interface MppInfo {
7
+ supported: boolean;
8
+ enabled: boolean;
9
+ protocol: string;
10
+ version: string;
11
+ methods: string[];
12
+ pricing: MppPricing;
13
+ limits: MppLimits;
14
+ }
15
+ export interface MppPricing {
16
+ perGbCents: number;
17
+ depositMinCents: number;
18
+ currency: string;
19
+ }
20
+ export interface MppLimits {
21
+ maxDepositCents: number;
22
+ maxSessionDurationSeconds: number;
23
+ }
24
+ export interface MppTopUpResponse {
25
+ success: boolean;
26
+ amountCents: number;
27
+ method: string;
28
+ transactionId: string;
29
+ }
30
+ export interface MppSessionResponse {
31
+ channelId: string;
32
+ depositCents: number;
33
+ method: string;
34
+ poolType: string;
35
+ expiresAt: string;
36
+ }
37
+ export interface MppCloseResponse {
38
+ channelId: string;
39
+ refundedCents: number;
40
+ usedCents: number;
41
+ closed: boolean;
42
+ }
43
+ export interface MppSessionStatus {
44
+ channelId: string;
45
+ status: string;
46
+ depositCents: number;
47
+ usedCents: number;
48
+ method: string;
49
+ poolType: string;
50
+ createdAt: string;
51
+ expiresAt: string;
52
+ }
53
+ /**
54
+ * MPP challenge response returned by POST /api/mpp/challenge.
55
+ * Used for keyless proxy access -- AI agents can use the proxy
56
+ * without any API key by solving a challenge and paying per request.
57
+ */
58
+ export interface MppChallengeResponse {
59
+ challengeId: string;
60
+ nonce: string;
61
+ expiresAt: string;
62
+ poolType: string;
63
+ credential: MppCredentialPayload;
64
+ }
65
+ /**
66
+ * Credential payload for keyless MPP proxy access.
67
+ * Pass this to `buildProxyHeaders()` to construct the headers
68
+ * needed to route through the proxy without an API key.
69
+ */
70
+ export interface MppCredentialPayload {
71
+ challengeId: string;
72
+ nonce: string;
73
+ poolType: string;
74
+ sessionToken?: string;
75
+ }
76
+ /**
77
+ * Micropayment Payment Protocol (MPP) resource.
78
+ *
79
+ * Provides pay-per-use proxy sessions with real-time micropayment channels.
80
+ * Supports multiple payment methods: Tempo streaming, Stripe SPT, and Lightning.
81
+ *
82
+ * MPP also enables keyless proxy access for AI agents: call `getChallenge()` to
83
+ * obtain a credential, then use `buildProxyHeaders()` to construct the proxy
84
+ * Authorization header -- no API key needed.
85
+ */
86
+ export declare class MppResource {
87
+ private http;
88
+ constructor(http: HttpClient);
89
+ /**
90
+ * Get MPP protocol information including supported methods, pricing, and limits.
91
+ *
92
+ * This endpoint does not require authentication.
93
+ */
94
+ getInfo(): Promise<MppInfo>;
95
+ /**
96
+ * Request an MPP challenge for keyless proxy access.
97
+ *
98
+ * This endpoint does not require authentication. The returned credential
99
+ * can be used with `buildProxyHeaders()` to access the proxy without an API key.
100
+ *
101
+ * @param poolType - Proxy pool type: "dc" (datacenter, $3/GB) or "residential" ($5/GB)
102
+ */
103
+ getChallenge(poolType: "dc" | "residential"): Promise<MppChallengeResponse>;
104
+ /**
105
+ * Build proxy Authorization header for keyless MPP access.
106
+ *
107
+ * Returns headers that should be set on the HTTP CONNECT / proxy request
108
+ * to route through the proxy without an API key.
109
+ *
110
+ * @param credential - The credential payload from `getChallenge()`
111
+ * @returns Headers object with `Authorization: MPP <json>`
112
+ */
113
+ buildProxyHeaders(credential: MppCredentialPayload): Record<string, string>;
114
+ /**
115
+ * Build proxy session token header for ongoing MPP sessions.
116
+ *
117
+ * After opening a session, use the session token for subsequent requests
118
+ * within the same session.
119
+ *
120
+ * @param sessionToken - The session token from an active MPP session
121
+ * @returns Headers object with `MPP-SESSION-TOKEN`
122
+ */
123
+ buildSessionHeaders(sessionToken: string): Record<string, string>;
124
+ /**
125
+ * Top up MPP balance using the specified payment method.
126
+ *
127
+ * Requires authentication (wallet credit needs a user account).
128
+ *
129
+ * @param amountCents - Amount to top up in cents (must be > 0 and <= 2,147,483,647)
130
+ * @param method - Payment method: "tempo", "stripe_spt", or "lightning"
131
+ */
132
+ topUp(amountCents: number, method: "tempo" | "stripe_spt" | "lightning"): Promise<MppTopUpResponse>;
133
+ /**
134
+ * Open a new micropayment session channel.
135
+ *
136
+ * This endpoint does not require authentication -- anonymous agents can
137
+ * open sessions by providing a payment method and deposit.
138
+ *
139
+ * @param opts.maxDepositCents - Maximum deposit for the session in cents
140
+ * @param opts.method - Payment method identifier
141
+ * @param opts.poolType - Proxy pool type (e.g. "dc", "residential")
142
+ */
143
+ openSession(opts: {
144
+ maxDepositCents: number;
145
+ method: string;
146
+ poolType: string;
147
+ }): Promise<MppSessionResponse>;
148
+ /**
149
+ * Close an active micropayment session channel.
150
+ * Any unused deposit is refunded.
151
+ *
152
+ * @param channelId - The channel ID to close
153
+ */
154
+ closeSession(channelId: string): Promise<MppCloseResponse>;
155
+ /**
156
+ * Get the status of a micropayment session channel.
157
+ *
158
+ * @param channelId - The channel ID to query
159
+ */
160
+ getSession(channelId: string): Promise<MppSessionStatus>;
161
+ }
@@ -0,0 +1,128 @@
1
+ /** IETF MPP auth scheme name (official spec) */
2
+ export const MPP_AUTH_SCHEME = "Payment";
3
+ /** Legacy auth scheme name (backward compat) */
4
+ export const MPP_AUTH_SCHEME_LEGACY = "MPP";
5
+ /**
6
+ * Micropayment Payment Protocol (MPP) resource.
7
+ *
8
+ * Provides pay-per-use proxy sessions with real-time micropayment channels.
9
+ * Supports multiple payment methods: Tempo streaming, Stripe SPT, and Lightning.
10
+ *
11
+ * MPP also enables keyless proxy access for AI agents: call `getChallenge()` to
12
+ * obtain a credential, then use `buildProxyHeaders()` to construct the proxy
13
+ * Authorization header -- no API key needed.
14
+ */
15
+ export class MppResource {
16
+ http;
17
+ constructor(http) {
18
+ this.http = http;
19
+ }
20
+ /**
21
+ * Get MPP protocol information including supported methods, pricing, and limits.
22
+ *
23
+ * This endpoint does not require authentication.
24
+ */
25
+ async getInfo() {
26
+ return this.http.get("/api/mpp/info", false);
27
+ }
28
+ /**
29
+ * Request an MPP challenge for keyless proxy access.
30
+ *
31
+ * This endpoint does not require authentication. The returned credential
32
+ * can be used with `buildProxyHeaders()` to access the proxy without an API key.
33
+ *
34
+ * @param poolType - Proxy pool type: "dc" (datacenter, $3/GB) or "residential" ($5/GB)
35
+ */
36
+ async getChallenge(poolType) {
37
+ if (poolType !== "dc" && poolType !== "residential") {
38
+ throw new Error("poolType must be 'dc' or 'residential'");
39
+ }
40
+ return this.http.post("/api/mpp/challenge", { poolType }, false);
41
+ }
42
+ /**
43
+ * Build proxy Authorization header for keyless MPP access.
44
+ *
45
+ * Returns headers that should be set on the HTTP CONNECT / proxy request
46
+ * to route through the proxy without an API key.
47
+ *
48
+ * @param credential - The credential payload from `getChallenge()`
49
+ * @returns Headers object with `Authorization: MPP <json>`
50
+ */
51
+ buildProxyHeaders(credential) {
52
+ return {
53
+ Authorization: MPP_AUTH_SCHEME + " " + JSON.stringify(credential),
54
+ };
55
+ }
56
+ /**
57
+ * Build proxy session token header for ongoing MPP sessions.
58
+ *
59
+ * After opening a session, use the session token for subsequent requests
60
+ * within the same session.
61
+ *
62
+ * @param sessionToken - The session token from an active MPP session
63
+ * @returns Headers object with `MPP-SESSION-TOKEN`
64
+ */
65
+ buildSessionHeaders(sessionToken) {
66
+ if (!sessionToken || typeof sessionToken !== "string") {
67
+ throw new Error("sessionToken must be a non-empty string");
68
+ }
69
+ return {
70
+ "MPP-SESSION-TOKEN": sessionToken,
71
+ };
72
+ }
73
+ /**
74
+ * Top up MPP balance using the specified payment method.
75
+ *
76
+ * Requires authentication (wallet credit needs a user account).
77
+ *
78
+ * @param amountCents - Amount to top up in cents (must be > 0 and <= 2,147,483,647)
79
+ * @param method - Payment method: "tempo", "stripe_spt", or "lightning"
80
+ */
81
+ async topUp(amountCents, method) {
82
+ if (!Number.isInteger(amountCents) ||
83
+ amountCents <= 0 ||
84
+ amountCents > 2_147_483_647) {
85
+ throw new Error("amountCents must be a positive integer <= 2,147,483,647");
86
+ }
87
+ return this.http.post("/api/mpp/topup", { amountCents, method });
88
+ }
89
+ /**
90
+ * Open a new micropayment session channel.
91
+ *
92
+ * This endpoint does not require authentication -- anonymous agents can
93
+ * open sessions by providing a payment method and deposit.
94
+ *
95
+ * @param opts.maxDepositCents - Maximum deposit for the session in cents
96
+ * @param opts.method - Payment method identifier
97
+ * @param opts.poolType - Proxy pool type (e.g. "dc", "residential")
98
+ */
99
+ async openSession(opts) {
100
+ if (!Number.isInteger(opts.maxDepositCents) ||
101
+ opts.maxDepositCents <= 0 ||
102
+ opts.maxDepositCents > 2_147_483_647) {
103
+ throw new Error("maxDepositCents must be a positive integer <= 2,147,483,647");
104
+ }
105
+ return this.http.post("/api/mpp/session/open", {
106
+ maxDepositCents: opts.maxDepositCents,
107
+ method: opts.method,
108
+ poolType: opts.poolType,
109
+ }, false);
110
+ }
111
+ /**
112
+ * Close an active micropayment session channel.
113
+ * Any unused deposit is refunded.
114
+ *
115
+ * @param channelId - The channel ID to close
116
+ */
117
+ async closeSession(channelId) {
118
+ return this.http.post("/api/mpp/session/close", { channelId });
119
+ }
120
+ /**
121
+ * Get the status of a micropayment session channel.
122
+ *
123
+ * @param channelId - The channel ID to query
124
+ */
125
+ async getSession(channelId) {
126
+ return this.http.get(`/api/mpp/session/${encodeURIComponent(channelId)}`);
127
+ }
128
+ }
@@ -22,7 +22,9 @@ export class TeamsResource {
22
22
  return this.http.delete(`/api/teams/${encodeURIComponent(teamId)}`);
23
23
  }
24
24
  async fundWallet(teamId, amountCents) {
25
- if (!Number.isInteger(amountCents) || amountCents <= 0 || amountCents > 2_147_483_647) {
25
+ if (!Number.isInteger(amountCents) ||
26
+ amountCents <= 0 ||
27
+ amountCents > 2_147_483_647) {
26
28
  throw new Error("amountCents must be a positive integer <= 2,147,483,647");
27
29
  }
28
30
  return this.http.post(`/api/teams/${encodeURIComponent(teamId)}/wallet/fund`, { amountCents });
@@ -67,7 +69,9 @@ export class TeamsResource {
67
69
  return this.http.post(`/api/teams/invites/${encodeURIComponent(token)}/accept`, {});
68
70
  }
69
71
  async createKey(teamId, label) {
70
- return this.http.post(`/api/teams/${encodeURIComponent(teamId)}/keys`, { label });
72
+ return this.http.post(`/api/teams/${encodeURIComponent(teamId)}/keys`, {
73
+ label,
74
+ });
71
75
  }
72
76
  async listKeys(teamId) {
73
77
  return this.http.get(`/api/teams/${encodeURIComponent(teamId)}/keys`);