@atumlabs/payment-gateway-client 2.0.0 → 2.1.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.0] - 2026-07-31
9
+
10
+ ### Added
11
+ - The CLIs read an optional `.env` file from the working directory, so `cp .env.example .env` configures them. Resolution order: a CLI flag, then the environment, then `.env`, then the built-in default. This applies to the CLIs only; the SDK reads the environment but never modifies it, so an application embedding the SDK stays in control of its own configuration.
12
+ - `getErrorResponse(err)` returns the typed, public-facing gateway error (`ErrorResponse` — `code`, `message`, `request_id?`, `docs_url?`, `domain?`) from a caught `ApiError`, or `undefined` for anything else; `isApiError(err)` type guard for the transport-level error. No internal error taxonomy is exposed.
13
+ - Idempotency and retries documentation (`docs/idempotency.md`) plus a summary in the README: the two guarantees (gateway dedup and on-chain single-settlement) and the per-chain differences (EVM/Tron vs Solana).
14
+ - The published package now ships `LICENSE` and an autogenerated `THIRD-PARTY-NOTICES.txt` (attributing the third-party components statically bundled into `dist/`).
15
+ - The gateway base URL now honors a `GATEWAY_URL` environment variable. Precedence: an explicit URL (SDK `{ BASE }` or the CLI `--gateway` flag), then `GATEWAY_URL`, then the built-in production-testnet default. A blank or whitespace-only `GATEWAY_URL` counts as unset and falls through to the default. An explicit `{ BASE: '' }` is used verbatim, which is how a caller targets a same-origin proxy.
16
+ - The exported `OpenAPI` configuration now reports this package's default gateway (production-testnet), matching what a client resolves when no URL is supplied. The OpenAPI contract continues to list the mainnet server first, in line with the other Atum service contracts.
17
+
18
+ ### Changed
19
+ - README signing example now uses the shipped signer helpers (`createSenderSigner` + `signPaymentRequest`) instead of manual signing, and the error-handling example reads the typed `ErrorResponse` fields.
20
+ - The idempotency docs now state the consequence of reusing a `request_id` with different terms: the gateway returns the original payment, so the new terms are silently dropped and a genuinely new payment needs a new id.
21
+ - The `fulfillment_verifier.endpoint` example in the OpenAPI spec is now a bare origin (`https://veri-fill.production-testnet.atum.xyz`) and its description says so. The field is a base URL to which the caller appends the verifier's own paths, so an example carrying `/v1/fulfillment` would double the path for anyone copying its shape.
22
+ - Two documentation links in the OpenAPI contract now point at `schemas.atum.xyz`. Descriptive text only: JSON-LD `@context` prefixes, schema `$id` values, and `did:web:` identifiers are unchanged, since those take part in signature canonicalization.
23
+ - The package is marked `restricted` and its `license` field is `SEE LICENSE IN LICENSE`. The publish guard now also fails on any inlined copyleft dependency, stale/incomplete third-party notices, missing license materials in the tarball, or an incorrect `license` field.
24
+ - Default gateway hosts point at the canonical `payment-gw.production-{testnet,mainnet}.atum.xyz` endpoints (the SDK/CLI default and the generated client default), replacing the retired `atumlabs.xyz` / `api.atum.network` hosts.
25
+
26
+ ### Fixed
27
+ - The CLIs (`send-payment`, `request-quote`, `quote-status`, `payment-status`) report the real package version via `--version` (they previously hardcoded `1.0.0`).
28
+ - `docs/` is now included in the published package. The README links to `docs/idempotency.md`, which had not been shipped, so the link was dead for anyone installing from npm.
29
+ - README corrections: the install instructions now distinguish a global install (for the command-line tools) from a project install (for the SDK), and the removal instructions match; the `.env` file and the gateway-URL precedence are documented; monorepo build detail moved to `CONTRIBUTING.md`.
30
+ - A zero-config client (`new PaymentGatewayClient()` with no `BASE`) now uses a single, consistent gateway host; previously it fetched chain defaults from the testnet host but submitted payments to the mainnet host.
31
+
8
32
  ## [2.0.0] - 2026-07-27
9
33
 
10
34
  ### Breaking
package/README.md CHANGED
@@ -2,25 +2,38 @@
2
2
 
3
3
  TypeScript client for Atum Payment Gateway API with CLI support.
4
4
 
5
+ > **Proprietary software - not open source.**
6
+ >
7
+ > Copyright (c) 2026 Atum Labs, Inc. All rights reserved. Access to and use of `@atumlabs/payment-gateway-client` are limited to entities expressly authorized by Atum and are governed by the Atum Payment Gateway Client Private Repository License Agreement in the LICENSE file included with this package. Do not redistribute, publish, mirror, sublicense, or provide this package to any unauthorized person. By accessing, installing, copying, or using the package, you agree to the license terms.
8
+
5
9
  > NOTE: Payments from EVM chains require prior ERC-20 approval on the source token for the Permit2 contract (0x000000000022D473030F116dDEE9F6B43aC78BA3 on virtually all EVM chains).
6
10
  >
7
- > (And the same applies for Tron/TRC-20, with a Permit2 address of TJhMXTHQHeQyMD7TcKQFqAePNgG4b31H9m on mainnet or TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`)
11
+ > (And the same applies for Tron/TRC-20, with a Permit2 address of TJhMXTHQHeQyMD7TcKQFqAePNgG4b31H9m on mainnet or TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta).
8
12
 
9
13
  ## Installation
10
14
 
11
15
  `@atumlabs/payment-gateway-client` is a private npm package. Once your npm account
12
- has been granted access, install it with npm:
16
+ has been granted access, install it with npm.
17
+
18
+ To use the SDK in a project:
13
19
 
14
20
  ```bash
15
21
  npm install @atumlabs/payment-gateway-client
16
22
  ```
17
23
 
18
- This also installs the `send-payment`, `request-quote`, `quote-status`, and
19
- `payment-status` CLI commands.
24
+ To use the command-line tools, install globally so they are on your `PATH`:
25
+
26
+ ```bash
27
+ npm install -g @atumlabs/payment-gateway-client
28
+ ```
29
+
30
+ A project-local install also provides the commands, under `node_modules/.bin`, so
31
+ `npx send-payment ...` works without a global install.
20
32
 
21
33
  ## CLI Usage
22
34
 
23
- After linking, the `send-payment` command is available globally:
35
+ The package provides four commands: `send-payment`, `request-quote`,
36
+ `quote-status`, and `payment-status`. After a global install:
24
37
 
25
38
  ```bash
26
39
  send-payment [options] <sender> <amount> <sourceAsset> <receiver> <destinationAsset>
@@ -38,8 +51,8 @@ send-payment [options] <sender> <amount> <sourceAsset> <receiver> <destinationAs
38
51
 
39
52
  - `-V, --version` - Output the version number
40
53
  - `--gateway <url>` - Payment gateway URL (default: testnet)
41
- - `--request-id <id>` - Custom request ID (overrides prefix)
42
- - `--request-id-prefix <prefix>` - Custom request ID prefix (default: `pmt-gw-cli`)
54
+ - `--request-id <id>` - Idempotency key; seeds the on-chain deposit nonce. Reuse the same id to retry a payment safely. Omitted: a one-shot id is generated and printed (see [Idempotency and retries](#idempotency-and-retries))
55
+ - `--request-id-prefix <prefix>` - Prefix for the auto-generated request id (default: `pmt-gw-cli`)
43
56
  - `-h, --help` - Display help
44
57
 
45
58
  ### CAIP-19 Asset Format Examples
@@ -75,19 +88,32 @@ export TURNKEY_API_PRIVATE_KEY=...
75
88
  send-payment --provider turnkey <args...>
76
89
  ```
77
90
 
78
- Turnkey signing uses the shared `@atum-labs/turnkey-signer` (and `@atum-labs/km-core`),
79
- which live in this monorepo under `key-management/` and are consumed as pnpm workspace
80
- packages (`workspace:*`), built locally by the `build:deps` step. `@solana/web3.js` and
81
- the other Turnkey deps are already declared, so no extra setup is required.
91
+ Everything Turnkey signing needs is already declared as a dependency, so no extra
92
+ setup is required. The Turnkey code is loaded on demand, so the private-key path
93
+ does not pull in Turnkey or `@solana/web3.js`.
94
+
95
+ ### Configuration file
96
+
97
+ The command-line tools also read an optional `.env` file from the directory you
98
+ run them in, so credentials and settings do not have to be retyped each time:
99
+
100
+ ```
101
+ PRIVATE_KEY=0x...
102
+ GATEWAY_URL=https://payment-gw.production-testnet.atum.xyz
103
+ SOLANA_RPC_URL=
104
+ TURNKEY_ORGANIZATION_ID=
105
+ TURNKEY_WALLET_ID=
106
+ TURNKEY_API_PUBLIC_KEY=
107
+ TURNKEY_API_PRIVATE_KEY=
108
+ ```
82
109
 
83
- Notes:
84
- - The shared packages are workspace members, so a root `pnpm install` links them, and
85
- `pnpm run build` and `pnpm test` build them first (`build:deps`).
86
- - The Turnkey code is loaded lazily (`import('./turnkey-impl')`), so the private-key
87
- path never pulls in Turnkey or `@solana/web3.js`.
88
- - For publishing, the build (tsup) bundles the shared `@atum-labs/*` packages directly
89
- into `dist`, so the published package is self-contained with no `@atum-labs/*` runtime
90
- dependencies. The siblings stay `workspace:*` devDependencies used only at build time.
110
+ Where a setting has a matching flag, the flag takes precedence, then a value
111
+ already set in your environment, then `.env`, then the built-in default. Keep the
112
+ file out of version control — it holds signing keys.
113
+
114
+ This applies to the command-line tools only. The SDK does not read `.env`; pass
115
+ configuration as arguments, or set `GATEWAY_URL` in your own application's
116
+ environment.
91
117
 
92
118
  ### Output
93
119
 
@@ -105,12 +131,10 @@ PRIVATE_KEY=0xabc... send-payment \
105
131
  tron:shasta/trc20:TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs
106
132
  ```
107
133
 
108
- ### Unlinking
109
-
110
- To remove the global CLI command:
134
+ ### Removing the command-line tools
111
135
 
112
136
  ```bash
113
- npm unlink -g @atumlabs/payment-gateway-client
137
+ npm uninstall -g @atumlabs/payment-gateway-client
114
138
  ```
115
139
 
116
140
  ## SDK Usage
@@ -118,18 +142,31 @@ npm unlink -g @atumlabs/payment-gateway-client
118
142
  ### Basic Setup
119
143
 
120
144
  ```typescript
121
- import {
145
+ import {
122
146
  PaymentGatewayClient,
147
+ createSenderSigner,
148
+ signPaymentRequest,
149
+ getErrorResponse,
123
150
  type PaymentResponse,
124
- ApiError
151
+ ApiError,
125
152
  } from '@atumlabs/payment-gateway-client';
126
- import { ethers } from 'ethers';
127
153
 
128
154
  const client = new PaymentGatewayClient({
129
- BASE: 'https://payment-gateway.atumlabs.xyz' // or your gateway URL
155
+ BASE: 'https://payment-gw.production-testnet.atum.xyz' // or your gateway URL
130
156
  });
131
157
  ```
132
158
 
159
+ ### Gateway URL
160
+
161
+ The client uses the production-testnet gateway by default. To target another
162
+ environment, in order of precedence:
163
+
164
+ 1. Pass it explicitly — SDK `new PaymentGatewayClient({ BASE })`, or the CLI `--gateway` flag.
165
+ 2. Set the `GATEWAY_URL` environment variable.
166
+ 3. Otherwise the built-in default `https://payment-gw.production-testnet.atum.xyz` is used.
167
+
168
+ Mainnet access is granted by Atum; use the mainnet gateway URL provided to you.
169
+
133
170
  ### Example: Tron to Celo Sepolia Payment
134
171
 
135
172
  ```typescript
@@ -149,15 +186,22 @@ async function sendPayment() {
149
186
  fulfillmentAmount: '100000', // 0.10 USDT (6 decimals)
150
187
  sourceAsset: 'tron:shasta/trc20:TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs', // USDT on Tron Shasta
151
188
  destinationAccount: '0xYourEthereumAddressHere',
152
- destinationAsset: 'eip155:11142220/erc20:0x456a3D042C0DbD3db53D5489e98dFb038553B0d0' // USDC on Celo Sepolia
189
+ destinationAsset: 'eip155:11142220/erc20:0x456a3D042C0DbD3db53D5489e98dFb038553B0d0', // USDC on Celo Sepolia
190
+ // Required. Your stable idempotency key — reuse the SAME value on retry so a
191
+ // retry never becomes a second payment (see "Idempotency and retries" below).
192
+ requestId: 'order-4711',
153
193
  });
154
194
 
155
- // Sign the message (Tron uses the same signing as Ethereum, but without the 0x private key prefix)
156
- const wallet = new ethers.Wallet(privateKey.replace(/^0x/, ''));
157
- paymentRequest.sender_auth.signed_messages[0].signature =
158
- wallet.signingKey.sign(
159
- paymentRequest.sender_auth.signed_messages[0].message
160
- ).serialized;
195
+ // Sign the prepared request with the SDK signer helper. It handles the
196
+ // per-chain signing differences internally (EVM typed-data, Tron hash,
197
+ // Solana Ed25519), so you never touch a chain library directly.
198
+ const sourceChainId = 'tron:shasta'; // CAIP-2 chain id, i.e. sourceAsset.split('/')[0]
199
+ const signer = createSenderSigner(sourceChainId, {
200
+ provider: 'raw',
201
+ privateKey,
202
+ pinnedAddress: tronSender,
203
+ });
204
+ await signPaymentRequest(paymentRequest, signer);
161
205
 
162
206
  try {
163
207
  // Submit the payment
@@ -172,9 +216,11 @@ async function sendPayment() {
172
216
 
173
217
  return response;
174
218
  } catch (error) {
175
- if (error instanceof ApiError) {
176
- console.error('API Error:', error.status, error.statusText);
177
- console.error('Response:', error.body);
219
+ const gwError = getErrorResponse(error);
220
+ if (gwError) {
221
+ console.error('Gateway error:', gwError.code, gwError.message, gwError.request_id);
222
+ } else if (error instanceof ApiError) {
223
+ console.error('HTTP', error.status, error.statusText, error.url);
178
224
  }
179
225
  throw error;
180
226
  }
@@ -183,15 +229,29 @@ async function sendPayment() {
183
229
 
184
230
  ### Error Handling
185
231
 
186
- The SDK provides detailed error information through the `ApiError` type:
232
+ The gateway returns a typed, public error body — `ErrorResponse`
233
+ (`{ code, message, request_id?, docs_url?, domain? }`). Use `getErrorResponse`
234
+ to narrow a caught error to it; it returns `undefined` for anything that is not
235
+ a gateway error with that shape. For transport-level detail (HTTP status, URL),
236
+ the thrown value is still an `ApiError`.
187
237
 
188
238
  ```typescript
189
- catch (error) {
190
- if (error instanceof ApiError) {
191
- console.error('Status:', error.status);
192
- console.error('Status Text:', error.statusText);
193
- console.error('URL:', error.url);
194
- console.error('Response Body:', error.body);
239
+ import { getErrorResponse, ApiError } from '@atumlabs/payment-gateway-client';
240
+
241
+ try {
242
+ await client.payments.submitPayment({ requestBody: paymentRequest });
243
+ } catch (error) {
244
+ const gwError = getErrorResponse(error);
245
+ if (gwError) {
246
+ console.error('Code:', gwError.code); // machine-readable category
247
+ console.error('Message:', gwError.message); // safe, human-readable text
248
+ console.error('Request ID:', gwError.request_id); // quote this to support
249
+ console.error('Docs:', gwError.docs_url);
250
+ } else if (error instanceof ApiError) {
251
+ // Transport-level failure with no typed body (e.g. a proxy/gateway error).
252
+ console.error('HTTP', error.status, error.statusText, error.url);
253
+ } else {
254
+ throw error;
195
255
  }
196
256
  }
197
257
  ```
@@ -203,13 +263,29 @@ Assets are identified using the [CAIP-19](https://chainagnostic.org/CAIPs/caip-1
203
263
  - Tron example: `tron:shasta/trc20:TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs`
204
264
  - EVM example: `eip155:11142220/erc20:0x456a3D042C0DbD3db53D5489e98dFb038553B0d0`
205
265
 
206
- ## Package Structure
266
+ ## Idempotency and retries
267
+
268
+ Every payment carries a `request_id`. Pass a stable value and reuse the exact
269
+ same one on every retry (a timeout, a network blip, a restart) and you end up
270
+ with one payment, not two — and you get the same answer each time.
271
+
272
+ - Using this SDK, `request_id` is **required** on the payment path
273
+ (`preparePaymentRequest`), and it is the only thing you manage: the SDK derives
274
+ the on-chain deposit nonce deterministically from it, so retries line up on
275
+ their own. Reuse the same `request_id` to retry safely.
276
+ - On the CLI, `--request-id` is optional; when omitted a one-shot id is generated
277
+ and printed, so you can re-run with `--request-id <id>` to retry the same
278
+ payment.
279
+ - A genuinely new payment needs a **new** `request_id`. Reusing one with different
280
+ terms (a corrected amount, a different token) returns the original payment
281
+ rather than an error, so the new terms are silently dropped.
207
282
 
208
- - `src/` - Source TypeScript files
209
- - `generated/` - Auto-generated API client from OpenAPI spec
210
- - `cli/` - CLI implementation
211
- - `dist/` - Pre-compiled JavaScript (ready to use)
283
+ See [docs/idempotency.md](docs/idempotency.md) for the full model: the two
284
+ guarantees and the per-chain differences (EVM/Tron vs Solana).
212
285
 
213
- ---
286
+ ## What is in the package
214
287
 
215
- This repository contains proprietary Atum Labs code. Access is restricted and governed by the Private Repository License included in this repo.
288
+ - `dist/` — compiled JavaScript and TypeScript declarations, ready to use
289
+ - `dist/cli/` — the four command-line tools
290
+ - `docs/` — reference documentation, including [idempotency and retries](docs/idempotency.md)
291
+ - `LICENSE`, `THIRD-PARTY-NOTICES.txt` — license terms and third-party attribution
@@ -0,0 +1,45 @@
1
+ THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
2
+ ==============================================================================
3
+ @atumlabs/payment-gateway-client
4
+
5
+ The published artifact of this package (the compiled code under dist/) statically
6
+ bundles the third-party open-source components listed below; their source is
7
+ redistributed within this package, so their license and copyright notices are
8
+ reproduced here. Components and versions were taken from the exact modules the
9
+ build inlined. This file does NOT cover packages the consumer installs separately
10
+ as dependencies of this package (for example @solana/web3.js, axios, ethers, bs58,
11
+ commander, dotenv, tweetnacl, and zod) — those ship under their own licenses and are not
12
+ redistributed here.
13
+
14
+ LICENSE SUMMARY (1 component)
15
+ ------------------------------------------------------------------------------
16
+ 1 MIT
17
+ ==============================================================================
18
+
19
+ ------------------------------------------------------------------------------
20
+ @noble/hashes 1.8.0 (MIT)
21
+ Author: Paul Miller (https://paulmillr.com)
22
+ ------------------------------------------------------------------------------
23
+
24
+ The MIT License (MIT)
25
+
26
+ Copyright (c) 2022 Paul Miller (https://paulmillr.com)
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining a copy
29
+ of this software and associated documentation files (the “Software”), to deal
30
+ in the Software without restriction, including without limitation the rights
31
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32
+ copies of the Software, and to permit persons to whom the Software is
33
+ furnished to do so, subject to the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be included in
36
+ all copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
+ THE SOFTWARE.
45
+
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ /*
3
+ * Copyright (c) 2026 Atum Labs, Inc. All rights reserved.
4
+ * Proprietary and confidential.
5
+ * Access and use are governed by the LICENSE file distributed with this package.
6
+ * Do not remove, alter, or obscure this notice.
7
+ */
2
8
  "use strict";
3
9
  var __create = Object.create;
4
10
  var __defProp = Object.defineProperty;
@@ -2445,7 +2451,7 @@ var Interceptors = class {
2445
2451
  }
2446
2452
  };
2447
2453
  var OpenAPI = {
2448
- BASE: "https://api.atum.network",
2454
+ BASE: "https://payment-gw.production-mainnet.atum.xyz",
2449
2455
  CREDENTIALS: "include",
2450
2456
  ENCODE_PATH: void 0,
2451
2457
  HEADERS: void 0,
@@ -2462,8 +2468,8 @@ var OpenAPI = {
2462
2468
 
2463
2469
  // src/generated/core/BaseHttpRequest.ts
2464
2470
  var BaseHttpRequest = class {
2465
- constructor(config) {
2466
- this.config = config;
2471
+ constructor(config2) {
2472
+ this.config = config2;
2467
2473
  }
2468
2474
  };
2469
2475
 
@@ -2614,15 +2620,15 @@ var getQueryString = (params) => {
2614
2620
  Object.entries(params).forEach(([key, value]) => encodePair(key, value));
2615
2621
  return qs.length ? `?${qs.join("&")}` : "";
2616
2622
  };
2617
- var getUrl = (config, options) => {
2618
- const encoder = config.ENCODE_PATH || encodeURI;
2619
- const path = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => {
2623
+ var getUrl = (config2, options) => {
2624
+ const encoder = config2.ENCODE_PATH || encodeURI;
2625
+ const path = options.url.replace("{api-version}", config2.VERSION).replace(/{(.*?)}/g, (substring, group) => {
2620
2626
  if (options.path?.hasOwnProperty(group)) {
2621
2627
  return encoder(String(options.path[group]));
2622
2628
  }
2623
2629
  return substring;
2624
2630
  });
2625
- const url = config.BASE + path;
2631
+ const url = config2.BASE + path;
2626
2632
  return options.query ? url + getQueryString(options.query) : url;
2627
2633
  };
2628
2634
  var getFormData = (options) => {
@@ -2652,12 +2658,12 @@ var resolve = async (options, resolver) => {
2652
2658
  }
2653
2659
  return resolver;
2654
2660
  };
2655
- var getHeaders = async (config, options) => {
2661
+ var getHeaders = async (config2, options) => {
2656
2662
  const [token, username, password, additionalHeaders] = await Promise.all([
2657
- resolve(options, config.TOKEN),
2658
- resolve(options, config.USERNAME),
2659
- resolve(options, config.PASSWORD),
2660
- resolve(options, config.HEADERS)
2663
+ resolve(options, config2.TOKEN),
2664
+ resolve(options, config2.USERNAME),
2665
+ resolve(options, config2.PASSWORD),
2666
+ resolve(options, config2.HEADERS)
2661
2667
  ]);
2662
2668
  const headers = Object.entries({
2663
2669
  Accept: "application/json",
@@ -2697,7 +2703,7 @@ var getRequestBody = (options) => {
2697
2703
  }
2698
2704
  return void 0;
2699
2705
  };
2700
- var sendRequest = async (config, options, url, body, formData, headers, onCancel, axiosClient) => {
2706
+ var sendRequest = async (config2, options, url, body, formData, headers, onCancel, axiosClient) => {
2701
2707
  const controller = new AbortController();
2702
2708
  let requestConfig = {
2703
2709
  data: body ?? formData,
@@ -2705,10 +2711,10 @@ var sendRequest = async (config, options, url, body, formData, headers, onCancel
2705
2711
  method: options.method,
2706
2712
  signal: controller.signal,
2707
2713
  url,
2708
- withCredentials: config.WITH_CREDENTIALS
2714
+ withCredentials: config2.WITH_CREDENTIALS
2709
2715
  };
2710
2716
  onCancel(() => controller.abort());
2711
- for (const fn of config.interceptors.request._fns) {
2717
+ for (const fn of config2.interceptors.request._fns) {
2712
2718
  requestConfig = await fn(requestConfig);
2713
2719
  }
2714
2720
  try {
@@ -2801,16 +2807,16 @@ var catchErrorCodes = (options, result) => {
2801
2807
  );
2802
2808
  }
2803
2809
  };
2804
- var request = (config, options, axiosClient = import_axios.default) => {
2810
+ var request = (config2, options, axiosClient = import_axios.default) => {
2805
2811
  return new CancelablePromise(async (resolve2, reject, onCancel) => {
2806
2812
  try {
2807
- const url = getUrl(config, options);
2813
+ const url = getUrl(config2, options);
2808
2814
  const formData = getFormData(options);
2809
2815
  const body = getRequestBody(options);
2810
- const headers = await getHeaders(config, options);
2816
+ const headers = await getHeaders(config2, options);
2811
2817
  if (!onCancel.isCancelled) {
2812
- let response = await sendRequest(config, options, url, body, formData, headers, onCancel, axiosClient);
2813
- for (const fn of config.interceptors.response._fns) {
2818
+ let response = await sendRequest(config2, options, url, body, formData, headers, onCancel, axiosClient);
2819
+ for (const fn of config2.interceptors.response._fns) {
2814
2820
  response = await fn(response);
2815
2821
  }
2816
2822
  const responseBody = getResponseBody(response);
@@ -2833,8 +2839,8 @@ var request = (config, options, axiosClient = import_axios.default) => {
2833
2839
 
2834
2840
  // src/generated/core/AxiosHttpRequest.ts
2835
2841
  var AxiosHttpRequest = class extends BaseHttpRequest {
2836
- constructor(config) {
2837
- super(config);
2842
+ constructor(config2) {
2843
+ super(config2);
2838
2844
  }
2839
2845
  /**
2840
2846
  * Request method
@@ -3166,20 +3172,20 @@ var HealthService = class {
3166
3172
 
3167
3173
  // src/generated/PaymentGatewayClient.ts
3168
3174
  var PaymentGatewayClient = class {
3169
- constructor(config, HttpRequest = AxiosHttpRequest) {
3175
+ constructor(config2, HttpRequest = AxiosHttpRequest) {
3170
3176
  this.request = new HttpRequest({
3171
- BASE: config?.BASE ?? "https://api.atum.network",
3172
- VERSION: config?.VERSION ?? "1.0.0",
3173
- WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false,
3174
- CREDENTIALS: config?.CREDENTIALS ?? "include",
3175
- TOKEN: config?.TOKEN,
3176
- USERNAME: config?.USERNAME,
3177
- PASSWORD: config?.PASSWORD,
3178
- HEADERS: config?.HEADERS,
3179
- ENCODE_PATH: config?.ENCODE_PATH,
3177
+ BASE: config2?.BASE ?? "https://payment-gw.production-mainnet.atum.xyz",
3178
+ VERSION: config2?.VERSION ?? "1.0.0",
3179
+ WITH_CREDENTIALS: config2?.WITH_CREDENTIALS ?? false,
3180
+ CREDENTIALS: config2?.CREDENTIALS ?? "include",
3181
+ TOKEN: config2?.TOKEN,
3182
+ USERNAME: config2?.USERNAME,
3183
+ PASSWORD: config2?.PASSWORD,
3184
+ HEADERS: config2?.HEADERS,
3185
+ ENCODE_PATH: config2?.ENCODE_PATH,
3180
3186
  interceptors: {
3181
- request: config?.interceptors?.request ?? new Interceptors(),
3182
- response: config?.interceptors?.response ?? new Interceptors()
3187
+ request: config2?.interceptors?.request ?? new Interceptors(),
3188
+ response: config2?.interceptors?.response ?? new Interceptors()
3183
3189
  }
3184
3190
  });
3185
3191
  this.authorizations = new AuthorizationsService(this.request);
@@ -3389,7 +3395,8 @@ var import_payment_request_sender_auth = __toESM(require_dist4());
3389
3395
 
3390
3396
  // src/index.ts
3391
3397
  var PAYMENT_REQUEST_VERSION = "1.0";
3392
- var defaultGateway = "https://payment-gateway-testnet.atumlabs.xyz";
3398
+ var defaultGateway = "https://payment-gw.production-testnet.atum.xyz";
3399
+ var OpenAPI2 = { ...OpenAPI, BASE: defaultGateway };
3393
3400
  var DEFAULT_QUOTE_DEADLINE_SECONDS = 5;
3394
3401
  var DEFAULT_FULFILLMENT_DEADLINE_SECONDS = 3600;
3395
3402
  var DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS = 10;
@@ -3477,9 +3484,11 @@ async function assemblePaymentRequest(params) {
3477
3484
  };
3478
3485
  }
3479
3486
  var PaymentGatewayClient2 = class extends PaymentGatewayClient {
3480
- constructor(config, HttpRequest = AxiosHttpRequest) {
3481
- super(config, HttpRequest);
3482
- this.baseUrl = config?.BASE ?? defaultGateway;
3487
+ constructor(config2, HttpRequest = AxiosHttpRequest) {
3488
+ const envBase = (typeof process !== "undefined" ? process.env.GATEWAY_URL : void 0)?.trim();
3489
+ const base = config2?.BASE ?? (envBase || defaultGateway);
3490
+ super({ ...config2, BASE: base }, HttpRequest);
3491
+ this.baseUrl = base;
3483
3492
  }
3484
3493
  /**
3485
3494
  * Fetches chain defaults from the payment gateway.
@@ -3694,9 +3703,19 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
3694
3703
  }
3695
3704
  };
3696
3705
 
3706
+ // src/version.ts
3707
+ var PACKAGE_VERSION = true ? "2.1.0" : "0.0.0-dev";
3708
+
3709
+ // src/cli/load-env.ts
3710
+ var import_dotenv = require("dotenv");
3711
+ function loadCliEnv() {
3712
+ (0, import_dotenv.config)({ override: false, quiet: true });
3713
+ }
3714
+
3697
3715
  // src/cli/payment-status.ts
3716
+ loadCliEnv();
3698
3717
  var program = new import_commander.Command();
3699
- program.name("payment-status").description("Fetch the status of a payment (no signing required)").version("1.0.0").argument("<paymentId>", "The payment_id returned by send-payment (or a Quote-API award)").option("--gateway <url>", "Payment gateway URL", defaultGateway).addHelpText("after", `
3718
+ program.name("payment-status").description("Fetch the status of a payment (no signing required)").version(PACKAGE_VERSION).argument("<paymentId>", "The payment_id returned by send-payment (or a Quote-API award)").option("--gateway <url>", "Payment gateway URL (overrides GATEWAY_URL env; default: production-testnet)").addHelpText("after", `
3700
3719
  Example:
3701
3720
  payment-status --gateway http://localhost:8080 0x<payment_id>
3702
3721