Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion packages/payments/src/resources/environments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import {
type PaymentsEnvironmentFieldsFragment,
type SimplePaymentsEnvironmentFieldsFragment,
} from '../generated/sdk.js';
import { translateSdkErrors } from './sdkErrors.js';

export class Environments {
readonly #sdk: ReturnType<typeof getSdk>;

constructor(graphqlClient: GraphQLClient) {
this.#sdk = getSdk(graphqlClient);
this.#sdk = getSdk(graphqlClient, translateSdkErrors);
}

async list(): Promise<SimplePaymentsEnvironmentFieldsFragment[]> {
Expand Down
22 changes: 22 additions & 0 deletions packages/payments/src/resources/sdkErrors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import { ApiError } from '@ambosstech/core';

import { Payments } from '../client.js';

describe('resource error translation', () => {
it('translates a GraphQL error from a resource call into ApiError', async () => {
const fetchImpl: typeof fetch = async () =>
new Response(JSON.stringify({ errors: [{ message: 'boom' }] }), {
status: 200,
headers: { 'content-type': 'application/json' },
});
const payments = new Payments({ serviceApiKey: 'amb_live_test', fetch: fetchImpl });

await assert.rejects(
() => payments.environments.list(),
(err: unknown) => err instanceof ApiError && err.message === 'boom',
);
});
});
18 changes: 18 additions & 0 deletions packages/payments/src/resources/sdkErrors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AmbossClient } from '@ambosstech/core';

import type { SdkFunctionWrapper } from '../generated/sdk.js';

/**
* Wraps every generated SDK operation so raw `graphql-request` errors are
* translated into the SDK's `ApiError` / `NetworkError`. Resource calls use
* the generated client directly (not `AmbossClient.gqlRequest`), so without
* this they would surface untranslated `ClientError`s, breaking the documented
* error contract.
*/
export const translateSdkErrors: SdkFunctionWrapper = async (action) => {
try {
return await action();
} catch (err) {
throw AmbossClient.translateError(err);
}
};
3 changes: 2 additions & 1 deletion packages/payments/src/resources/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { sendAssetPayment } from '../node/lit.js';
import { sendLndPayment } from '../node/lnd.js';
import type { PaymentLifecycleStatus } from '../node/types.js';
import { translateSdkErrors } from './sdkErrors.js';
import { selectSendNode } from './sendNode.js';
import type { SendDestination, SendParams, SendResult } from './transactions.types.js';

Expand Down Expand Up @@ -57,7 +58,7 @@ export class Transactions {
#teamId?: string;

constructor(graphqlClient: GraphQLClient) {
this.#sdk = getSdk(graphqlClient);
this.#sdk = getSdk(graphqlClient, translateSdkErrors);
}

async createReceive(
Expand Down
3 changes: 2 additions & 1 deletion packages/payments/src/resources/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import {
type PaymentsWalletFieldsFragment,
type SimplePaymentsWalletFieldsFragment,
} from '../generated/sdk.js';
import { translateSdkErrors } from './sdkErrors.js';

export class Wallets {
readonly #sdk: ReturnType<typeof getSdk>;

constructor(graphqlClient: GraphQLClient) {
this.#sdk = getSdk(graphqlClient);
this.#sdk = getSdk(graphqlClient, translateSdkErrors);
}

async list(params: { environmentId: string }): Promise<SimplePaymentsWalletFieldsFragment[]> {
Expand Down
Loading