@atxp/client 0.7.4 → 0.8.1

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.
Files changed (55) hide show
  1. package/dist/atxpClient.d.ts +1 -1
  2. package/dist/atxpClient.d.ts.map +1 -1
  3. package/dist/atxpClient.js +17 -2
  4. package/dist/atxpClient.js.map +1 -1
  5. package/dist/atxpFetcher.d.ts +5 -15
  6. package/dist/atxpFetcher.d.ts.map +1 -1
  7. package/dist/atxpFetcher.js +95 -229
  8. package/dist/atxpFetcher.js.map +1 -1
  9. package/dist/baseAccount.d.ts +10 -7
  10. package/dist/baseAccount.d.ts.map +1 -1
  11. package/dist/baseAccount.js +18 -8
  12. package/dist/baseAccount.js.map +1 -1
  13. package/dist/basePaymentMaker.d.ts +4 -3
  14. package/dist/basePaymentMaker.d.ts.map +1 -1
  15. package/dist/basePaymentMaker.js +20 -3
  16. package/dist/basePaymentMaker.js.map +1 -1
  17. package/dist/clientTestHelpers.d.ts.map +1 -1
  18. package/dist/destinationMakers/atxpDestinationMaker.d.ts +15 -0
  19. package/dist/destinationMakers/atxpDestinationMaker.d.ts.map +1 -0
  20. package/dist/destinationMakers/atxpDestinationMaker.js +128 -0
  21. package/dist/destinationMakers/atxpDestinationMaker.js.map +1 -0
  22. package/dist/destinationMakers/index.d.ts +9 -0
  23. package/dist/destinationMakers/index.d.ts.map +1 -0
  24. package/dist/destinationMakers/index.js +45 -0
  25. package/dist/destinationMakers/index.js.map +1 -0
  26. package/dist/destinationMakers/passthroughDestinationMaker.d.ts +8 -0
  27. package/dist/destinationMakers/passthroughDestinationMaker.d.ts.map +1 -0
  28. package/dist/destinationMakers/passthroughDestinationMaker.js +27 -0
  29. package/dist/destinationMakers/passthroughDestinationMaker.js.map +1 -0
  30. package/dist/index.cjs +566 -466
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.ts +102 -55
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +555 -467
  35. package/dist/index.js.map +1 -1
  36. package/dist/polygonConstants.d.ts +53 -0
  37. package/dist/polygonConstants.d.ts.map +1 -0
  38. package/dist/polygonConstants.js +84 -0
  39. package/dist/polygonConstants.js.map +1 -0
  40. package/dist/solanaAccount.d.ts +8 -4
  41. package/dist/solanaAccount.d.ts.map +1 -1
  42. package/dist/solanaAccount.js +16 -4
  43. package/dist/solanaAccount.js.map +1 -1
  44. package/dist/solanaPaymentMaker.d.ts +4 -3
  45. package/dist/solanaPaymentMaker.d.ts.map +1 -1
  46. package/dist/solanaPaymentMaker.js +24 -5
  47. package/dist/solanaPaymentMaker.js.map +1 -1
  48. package/dist/types.d.ts +5 -23
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/types.js.map +1 -1
  51. package/package.json +2 -2
  52. package/dist/atxpAccount.d.ts +0 -18
  53. package/dist/atxpAccount.d.ts.map +0 -1
  54. package/dist/atxpAccount.js +0 -123
  55. package/dist/atxpAccount.js.map +0 -1
@@ -3,7 +3,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
3
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
4
4
  type RequiredClientConfigFields = 'mcpServer' | 'account';
5
5
  type OptionalClientConfig = Omit<ClientConfig, RequiredClientConfigFields>;
6
- type BuildableClientConfigFields = 'oAuthDb' | 'logger';
6
+ type BuildableClientConfigFields = 'oAuthDb' | 'logger' | 'destinationMakers';
7
7
  export declare const DEFAULT_CLIENT_CONFIG: Required<Omit<OptionalClientConfig, BuildableClientConfigFields>>;
8
8
  export declare function buildClientConfig(args: ClientArgs): ClientConfig;
9
9
  export declare function buildStreamableTransport(args: ClientArgs): StreamableHTTPClientTransport;
@@ -1 +1 @@
1
- {"version":3,"file":"atxpClient.d.ts","sourceRoot":"","sources":["../src/atxpClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,KAAK,0BAA0B,GAAG,WAAW,GAAG,SAAS,CAAC;AAC1D,KAAK,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;AAC3E,KAAK,2BAA2B,GAAG,SAAS,GAAG,QAAQ,CAAC;AAYxD,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,IAAI,CAAC,oBAAoB,EAAE,2BAA2B,CAAC,CAiBnG,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAehE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,6BAA6B,CAQxF;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlE"}
1
+ {"version":3,"file":"atxpClient.d.ts","sourceRoot":"","sources":["../src/atxpClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAInG,KAAK,0BAA0B,GAAG,WAAW,GAAG,SAAS,CAAC;AAC1D,KAAK,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;AAC3E,KAAK,2BAA2B,GAAG,SAAS,GAAG,QAAQ,GAAG,mBAAmB,CAAC;AAY9E,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,IAAI,CAAC,oBAAoB,EAAE,2BAA2B,CAAC,CAkBnG,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CA8BhE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,6BAA6B,CAQxF;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlE"}
@@ -1,7 +1,8 @@
1
- import { DEFAULT_AUTHORIZATION_SERVER, ConsoleLogger, MemoryOAuthDb } from '@atxp/common';
1
+ import { DEFAULT_ATXP_ACCOUNTS_SERVER, DEFAULT_AUTHORIZATION_SERVER, ConsoleLogger, MemoryOAuthDb, ATXPAccount } from '@atxp/common';
2
2
  import { atxpFetch } from './atxpFetcher.js';
3
3
  import { Client } from './node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js';
4
4
  import { StreamableHTTPClientTransport } from './node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js';
5
+ import { createDestinationMakers } from './destinationMakers/index.js';
5
6
 
6
7
  // Detect if we're in a browser environment and bind fetch appropriately
7
8
  const getFetch = () => {
@@ -14,6 +15,7 @@ const getFetch = () => {
14
15
  };
15
16
  const DEFAULT_CLIENT_CONFIG = {
16
17
  allowedAuthorizationServers: [DEFAULT_AUTHORIZATION_SERVER],
18
+ atxpAccountsServer: DEFAULT_ATXP_ACCOUNTS_SERVER,
17
19
  approvePayment: async (_p) => true,
18
20
  fetchFn: getFetch(),
19
21
  oAuthChannelFetch: getFetch(),
@@ -43,7 +45,20 @@ function buildClientConfig(args) {
43
45
  const withDefaults = { ...envDefaults, ...args };
44
46
  const logger = withDefaults.logger ?? new ConsoleLogger();
45
47
  const oAuthDb = withDefaults.oAuthDb ?? new MemoryOAuthDb({ logger });
46
- const built = { oAuthDb, logger };
48
+ const fetchFn = withDefaults.fetchFn;
49
+ // Build destination makers if not provided
50
+ let accountsServer = withDefaults.atxpAccountsServer;
51
+ // QoL hack for unspecified accounts server - if the caller is passing an atxpAccount, then assume the origin for that
52
+ // is what we should use for the accounts server. In practice, the only option is accounts.atxp.ai,
53
+ // but this supports staging environment
54
+ if (args.atxpAccountsServer === undefined && withDefaults.account && withDefaults.account instanceof ATXPAccount) {
55
+ accountsServer = withDefaults.account.origin;
56
+ }
57
+ const destinationMakers = withDefaults.destinationMakers ?? createDestinationMakers({
58
+ atxpAccountsServer: accountsServer,
59
+ fetchFn
60
+ });
61
+ const built = { oAuthDb, logger, destinationMakers };
47
62
  return Object.freeze({ ...withDefaults, ...built });
48
63
  }
49
64
  function buildStreamableTransport(args) {
@@ -1 +1 @@
1
- {"version":3,"file":"atxpClient.js","sources":["../src/atxpClient.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAUA;AACA,MAAM,QAAQ,GAAG,MAAmB;AAClC,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE;;AAEvE,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IAC3B;;AAEA,IAAA,OAAO,KAAK;AACd,CAAC;AAEM,MAAM,qBAAqB,GAAsE;IACtG,2BAA2B,EAAE,CAAC,4BAA4B,CAAC;AAC3D,IAAA,cAAc,EAAE,OAAO,EAAE,KAAK,IAAI;IAClC,OAAO,EAAE,QAAQ,EAAE;IACnB,iBAAiB,EAAE,QAAQ,EAAE;IAC7B,SAAS,EAAE,KAAK;AAChB,IAAA,UAAU,EAAE;AACV,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,OAAO,EAAE;AACV,KAAA;AACD,IAAA,aAAa,EAAE;AACb,QAAA,YAAY,EAAE;AACf,KAAA;AACD,IAAA,WAAW,EAAE,cAAa,CAAC;AAC3B,IAAA,kBAAkB,EAAE,cAAa,CAAC;AAClC,IAAA,SAAS,EAAE,cAAa,CAAC;AACzB,IAAA,gBAAgB,EAAE,cAAa;;AAG3B,SAAU,iBAAiB,CAAC,IAAgB,EAAA;;IAEhD,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;AAC3C,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO;IACvC;;AAEA,IAAA,MAAM,WAAW,GAAG;AAClB,QAAA,GAAG,qBAAqB;AACxB,QAAA,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;KAClD;IACD,MAAM,YAAY,GAAG,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,EAAE;IAChD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,IAAI,aAAa,EAAE;AACzD,IAAA,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,IAAI,IAAI,aAAa,CAAC,EAAC,MAAM,EAAC,CAAC;AACnE,IAAA,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,MAAM,EAAC;AAChC,IAAA,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,CAAC;AACrD;AAEM,SAAU,wBAAwB,CAAC,IAAgB,EAAA;AACvD,IAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC;;AAGtC,IAAA,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC;AAEtC,IAAA,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAC,KAAK,EAAE,YAAY,EAAC,CAAC;AACnG,IAAA,OAAO,SAAS;AAClB;AAEO,eAAe,UAAU,CAAC,IAAgB,EAAA;AAC/C,IAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC;AACtC,IAAA,MAAM,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC;AAElD,IAAA,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,aAAa,CAAC;AAClE,IAAA,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;AAE/B,IAAA,OAAO,MAAM;AACf;;;;"}
1
+ {"version":3,"file":"atxpClient.js","sources":["../src/atxpClient.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { OAuthAuthenticationRequiredError, OAuthClient } from './oAuth.js';
2
- import { AccessToken, AuthorizationServerUrl, FetchLike, OAuthDb, PaymentRequestData, Logger, Network, Currency } from '@atxp/common';
2
+ import { AccessToken, AuthorizationServerUrl, FetchLike, OAuthDb, PaymentRequestData, Logger, Network, DestinationMaker, Account } from '@atxp/common';
3
3
  import type { PaymentMaker, ProspectivePayment, ClientConfig } from './types.js';
4
4
  import { McpError } from '@modelcontextprotocol/sdk/types.js';
5
5
  /**
@@ -12,10 +12,10 @@ import { McpError } from '@modelcontextprotocol/sdk/types.js';
12
12
  export declare function atxpFetch(config: ClientConfig): FetchLike;
13
13
  export declare class ATXPFetcher {
14
14
  protected oauthClient: OAuthClient;
15
- protected paymentMakers: Map<string, PaymentMaker>;
15
+ protected account: Account;
16
+ protected destinationMakers: Map<Network, DestinationMaker>;
16
17
  protected sideChannelFetch: FetchLike;
17
18
  protected db: OAuthDb;
18
- protected accountId: string;
19
19
  protected allowedAuthorizationServers: AuthorizationServerUrl[];
20
20
  protected approvePayment: (payment: ProspectivePayment) => Promise<boolean>;
21
21
  protected logger: Logger;
@@ -36,11 +36,9 @@ export declare class ATXPFetcher {
36
36
  error: Error;
37
37
  }) => Promise<void>;
38
38
  constructor(config: {
39
- accountId: string;
39
+ account: Account;
40
40
  db: OAuthDb;
41
- paymentMakers: {
42
- [key: string]: PaymentMaker;
43
- };
41
+ destinationMakers: Map<Network, DestinationMaker>;
44
42
  fetchFn?: FetchLike;
45
43
  sideChannelFetch?: FetchLike;
46
44
  strict?: boolean;
@@ -66,14 +64,6 @@ export declare class ATXPFetcher {
66
64
  }) => Promise<void>;
67
65
  });
68
66
  private defaultPaymentFailureHandler;
69
- /**
70
- * Resolves atxp_base or atxp_base_sepolia destinations to real base network destinations
71
- * by calling the payment_info endpoint to get the destination address and network
72
- */
73
- protected resolveAtxpBaseDestination(network: string, paymentInfoUrl: string, paymentRequestId: string, amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise<{
74
- destinationAddress: string;
75
- network: Network;
76
- } | null>;
77
67
  protected handleMultiDestinationPayment: (paymentRequestData: PaymentRequestData, paymentRequestUrl: string, paymentRequestId: string) => Promise<boolean>;
78
68
  protected handlePaymentRequestError: (paymentRequestError: McpError) => Promise<boolean>;
79
69
  protected getPaymentRequestData: (paymentRequestUrl: string) => Promise<PaymentRequestData | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"atxpFetcher.d.ts","sourceRoot":"","sources":["../src/atxpFetcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"atxpFetcher.d.ts","sourceRoot":"","sources":["../src/atxpFetcher.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { BigNumber } from 'bignumber.js';
2
1
  import { OAuthAuthenticationRequiredError, OAuthClient } from './oAuth.js';
3
2
  import { PAYMENT_REQUIRED_ERROR_CODE, isSSEResponse, parseMcpMessages, parsePaymentRequests, paymentRequiredError, DEFAULT_AUTHORIZATION_SERVER, ConsoleLogger, getIsReactNative, createReactNativeSafeFetch } from '@atxp/common';
4
3
  import { InsufficientFundsError, PaymentNetworkError } from './types.js';
4
+ import { BigNumber } from 'bignumber.js';
5
5
 
6
6
  /**
7
7
  * Creates an ATXP fetch wrapper that handles OAuth authentication and payments.
@@ -12,9 +12,9 @@ import { InsufficientFundsError, PaymentNetworkError } from './types.js';
12
12
  */
13
13
  function atxpFetch(config) {
14
14
  const fetcher = new ATXPFetcher({
15
- accountId: config.account.accountId,
15
+ account: config.account,
16
16
  db: config.oAuthDb,
17
- paymentMakers: config.account.paymentMakers,
17
+ destinationMakers: config.destinationMakers,
18
18
  fetchFn: config.fetchFn,
19
19
  sideChannelFetch: config.oAuthChannelFetch,
20
20
  allowInsecureRequests: config.allowHttp,
@@ -32,7 +32,8 @@ class ATXPFetcher {
32
32
  constructor(config) {
33
33
  this.defaultPaymentFailureHandler = async ({ payment, error }) => {
34
34
  if (error instanceof InsufficientFundsError) {
35
- this.logger.info(`PAYMENT FAILED: Insufficient ${error.currency} funds on ${payment.network}`);
35
+ const networkText = error.network ? ` on ${error.network}` : '';
36
+ this.logger.info(`PAYMENT FAILED: Insufficient ${error.currency} funds${networkText}`);
36
37
  this.logger.info(`Required: ${error.required} ${error.currency}`);
37
38
  if (error.available) {
38
39
  this.logger.info(`Available: ${error.available} ${error.currency}`);
@@ -40,7 +41,7 @@ class ATXPFetcher {
40
41
  this.logger.info(`Account: ${payment.accountId}`);
41
42
  }
42
43
  else if (error instanceof PaymentNetworkError) {
43
- this.logger.info(`PAYMENT FAILED: Network error on ${payment.network}: ${error.message}`);
44
+ this.logger.info(`PAYMENT FAILED: Network error: ${error.message}`);
44
45
  }
45
46
  else {
46
47
  this.logger.info(`PAYMENT FAILED: ${error.message}`);
@@ -50,43 +51,61 @@ class ATXPFetcher {
50
51
  if (!paymentRequestData.destinations || paymentRequestData.destinations.length === 0) {
51
52
  return false;
52
53
  }
53
- // Try each destination in order
54
- for (const dest of paymentRequestData.destinations) {
55
- // Convert amount to BigNumber since it comes as a string from JSON
56
- const amount = new BigNumber(dest.amount);
57
- // Resolve atxp_base destinations to real base network destinations
58
- let destinationAddress = dest.address;
59
- let destinationNetwork = dest.network;
60
- const resolved = await this.resolveAtxpBaseDestination(dest.network, dest.address, paymentRequestId, amount, dest.currency, dest.address, paymentRequestData.iss);
61
- if (resolved) {
62
- destinationAddress = resolved.destinationAddress;
63
- destinationNetwork = resolved.network;
64
- }
65
- const paymentMaker = this.paymentMakers.get(destinationNetwork);
66
- if (!paymentMaker) {
67
- this.logger.debug(`ATXP: payment network '${destinationNetwork}' not available, trying next destination`);
54
+ // Get sources from the account
55
+ const sources = await this.account.getSources();
56
+ // Apply destination mappers to transform destinations
57
+ // Convert PaymentRequestDestination[] to Destination[] for mapper compatibility
58
+ const mappedDestinations = [];
59
+ for (const option of paymentRequestData.destinations) {
60
+ const destinationMaker = this.destinationMakers.get(option.network);
61
+ if (!destinationMaker) {
62
+ this.logger.debug(`ATXP: destination maker for network '${option.network}' not available, trying next destination`);
68
63
  continue;
69
64
  }
70
- const prospectivePayment = {
71
- accountId: this.accountId,
72
- resourceUrl: paymentRequestData.resource?.toString() ?? '',
73
- resourceName: paymentRequestData.resourceName ?? '',
74
- network: destinationNetwork,
75
- currency: dest.currency,
76
- amount: amount,
77
- iss: paymentRequestData.iss ?? '',
78
- };
79
- if (!await this.approvePayment(prospectivePayment)) {
80
- this.logger.info(`ATXP: payment request denied by callback function for destination on ${destinationNetwork}`);
81
- continue;
65
+ mappedDestinations.push(...(await destinationMaker.makeDestinations(option, this.logger, paymentRequestId, sources)));
66
+ }
67
+ if (mappedDestinations.length === 0) {
68
+ this.logger.info(`ATXP: no destinations found after mapping`);
69
+ return false;
70
+ }
71
+ // Validate amounts are not negative
72
+ for (const dest of mappedDestinations) {
73
+ if (dest.amount.isLessThan(0)) {
74
+ throw new Error(`ATXP: payment amount cannot be negative: ${dest.amount.toString()} ${dest.currency}`);
82
75
  }
83
- let paymentId;
76
+ }
77
+ // Create prospective payment for approval (using first destination for display)
78
+ const firstDest = mappedDestinations[0];
79
+ const prospectivePayment = {
80
+ accountId: this.account.accountId,
81
+ resourceUrl: paymentRequestData.resource?.toString() ?? '',
82
+ resourceName: paymentRequestData.resourceName ?? '',
83
+ currency: firstDest.currency,
84
+ amount: firstDest.amount,
85
+ iss: paymentRequestData.iss ?? '',
86
+ };
87
+ // Ask for approval once for all payment attempts
88
+ if (!await this.approvePayment(prospectivePayment)) {
89
+ this.logger.info(`ATXP: payment request denied by callback function`);
90
+ return false;
91
+ }
92
+ // Try each payment maker in order
93
+ let lastPaymentError = null;
94
+ let paymentAttempted = false;
95
+ for (const paymentMaker of this.account.paymentMakers) {
84
96
  try {
85
- paymentId = await paymentMaker.makePayment(amount, dest.currency, destinationAddress, paymentRequestData.iss);
86
- this.logger.info(`ATXP: made payment of ${amount.toString()} ${dest.currency} on ${destinationNetwork}: ${paymentId}`);
97
+ // Pass all destinations to payment maker - it will filter and pick the one it can handle
98
+ const result = await paymentMaker.makePayment(mappedDestinations, paymentRequestData.iss, paymentRequestId);
99
+ if (result === null) {
100
+ this.logger.debug(`ATXP: payment maker cannot handle these destinations, trying next`);
101
+ continue; // Try next payment maker
102
+ }
103
+ paymentAttempted = true;
104
+ // Payment was successful
105
+ this.logger.info(`ATXP: made payment of ${firstDest.amount.toString()} ${firstDest.currency} on ${result.chain}: ${result.transactionId}`);
87
106
  await this.onPayment({ payment: prospectivePayment });
88
107
  // Submit payment to the server
89
- const jwt = await paymentMaker.generateJWT({ paymentRequestId, codeChallenge: '' });
108
+ const jwt = await paymentMaker.generateJWT({ paymentRequestId, codeChallenge: '', accountId: this.account.accountId });
90
109
  const response = await this.sideChannelFetch(paymentRequestUrl.toString(), {
91
110
  method: 'PUT',
92
111
  headers: {
@@ -94,9 +113,10 @@ class ATXPFetcher {
94
113
  'Content-Type': 'application/json'
95
114
  },
96
115
  body: JSON.stringify({
97
- transactionId: paymentId,
98
- network: destinationNetwork,
99
- currency: dest.currency
116
+ transactionId: result.transactionId,
117
+ ...(result.transactionSubId ? { transactionSubId: result.transactionSubId } : {}),
118
+ chain: result.chain,
119
+ currency: result.currency
100
120
  })
101
121
  });
102
122
  this.logger.debug(`ATXP: payment was ${response.ok ? 'successfully' : 'not successfully'} PUT to ${paymentRequestUrl} : status ${response.status} ${response.statusText}`);
@@ -109,13 +129,18 @@ class ATXPFetcher {
109
129
  }
110
130
  catch (error) {
111
131
  const typedError = error;
112
- this.logger.warn(`ATXP: payment failed on ${destinationNetwork}: ${typedError.message}`);
132
+ paymentAttempted = true;
133
+ lastPaymentError = typedError;
134
+ this.logger.warn(`ATXP: payment maker failed: ${typedError.message}`);
113
135
  await this.onPaymentFailure({ payment: prospectivePayment, error: typedError });
114
- // Try next destination
115
- continue;
136
+ // Continue to next payment maker
116
137
  }
117
138
  }
118
- this.logger.info(`ATXP: no suitable payment destination found among ${paymentRequestData.destinations.length} options`);
139
+ // If payment was attempted but all failed, rethrow the last error
140
+ if (paymentAttempted && lastPaymentError) {
141
+ throw lastPaymentError;
142
+ }
143
+ this.logger.info(`ATXP: no payment maker could handle these destinations`);
119
144
  return false;
120
145
  };
121
146
  this.handlePaymentRequestError = async (paymentRequestError) => {
@@ -142,102 +167,8 @@ class ATXPFetcher {
142
167
  if (paymentRequestData.destinations && paymentRequestData.destinations.length > 0) {
143
168
  return this.handleMultiDestinationPayment(paymentRequestData, paymentRequestUrl, paymentRequestId);
144
169
  }
145
- // Handle legacy single destination format
146
- const requestedNetwork = paymentRequestData.network;
147
- if (!requestedNetwork) {
148
- throw new Error(`Payment network not provided`);
149
- }
150
- const destination = paymentRequestData.destination;
151
- if (!destination) {
152
- throw new Error(`destination not provided`);
153
- }
154
- let amount = new BigNumber(0);
155
- if (!paymentRequestData.amount) {
156
- throw new Error(`amount not provided`);
157
- }
158
- try {
159
- amount = new BigNumber(paymentRequestData.amount);
160
- }
161
- catch {
162
- throw new Error(`Invalid amount ${paymentRequestData.amount}`);
163
- }
164
- if (amount.lte(0)) {
165
- throw new Error(`Invalid amount ${paymentRequestData.amount}`);
166
- }
167
- const currency = paymentRequestData.currency;
168
- if (!currency) {
169
- throw new Error(`Currency not provided`);
170
- }
171
- // Resolve atxp_base destinations to real base network destinations
172
- let destinationAddress = destination;
173
- let destinationNetwork = requestedNetwork;
174
- const resolved = await this.resolveAtxpBaseDestination(requestedNetwork, destination, paymentRequestId, amount, currency, destination, paymentRequestData.iss);
175
- if (resolved) {
176
- destinationAddress = resolved.destinationAddress;
177
- destinationNetwork = resolved.network;
178
- }
179
- const paymentMaker = this.paymentMakers.get(destinationNetwork);
180
- if (!paymentMaker) {
181
- this.logger.info(`ATXP: payment network '${destinationNetwork}' not set up for this client (available networks: ${Array.from(this.paymentMakers.keys()).join(', ')})`);
182
- return false;
183
- }
184
- const prospectivePayment = {
185
- accountId: this.accountId,
186
- resourceUrl: paymentRequestData.resource?.toString() ?? '',
187
- resourceName: paymentRequestData.resourceName ?? '',
188
- network: destinationNetwork,
189
- currency,
190
- amount,
191
- iss: paymentRequestData.iss ?? '',
192
- };
193
- if (!await this.approvePayment(prospectivePayment)) {
194
- this.logger.info(`ATXP: payment request denied by callback function`);
195
- return false;
196
- }
197
- let paymentId;
198
- try {
199
- paymentId = await paymentMaker.makePayment(amount, currency, destinationAddress, paymentRequestData.iss);
200
- this.logger.info(`ATXP: made payment of ${amount} ${currency} on ${destinationNetwork}: ${paymentId}`);
201
- // Call onPayment callback after successful payment
202
- await this.onPayment({ payment: prospectivePayment });
203
- }
204
- catch (paymentError) {
205
- // Call onPaymentFailure callback if payment fails
206
- await this.onPaymentFailure({
207
- payment: prospectivePayment,
208
- error: paymentError
209
- });
210
- throw paymentError;
211
- }
212
- const jwt = await paymentMaker.generateJWT({ paymentRequestId, codeChallenge: '' });
213
- // Make a fetch call to the authorization URL with the payment ID
214
- // redirect=false is a hack
215
- // The OAuth spec calls for the authorization url to return with a redirect, but fetch
216
- // on mobile will automatically follow the redirect (it doesn't support the redirect=manual option)
217
- // We want the redirect URL so we can extract the code from it, not the contents of the
218
- // redirect URL (which might not even exist for agentic ATXP clients)
219
- // So ATXP servers are set up to instead return a 200 with the redirect URL in the body
220
- // if we pass redirect=false.
221
- // TODO: Remove the redirect=false hack once we have a way to handle the redirect on mobile
222
- const response = await this.sideChannelFetch(paymentRequestUrl.toString(), {
223
- method: 'PUT',
224
- headers: {
225
- 'Authorization': `Bearer ${jwt}`,
226
- 'Content-Type': 'application/json'
227
- },
228
- body: JSON.stringify({
229
- transactionId: paymentId,
230
- network: destinationNetwork,
231
- currency: currency
232
- })
233
- });
234
- this.logger.debug(`ATXP: payment was ${response.ok ? 'successfully' : 'not successfully'} PUT to ${paymentRequestUrl} : status ${response.status} ${response.statusText}`);
235
- if (!response.ok) {
236
- const msg = `ATXP: payment to ${paymentRequestUrl} failed: HTTP ${response.status} ${await response.text()}`;
237
- this.logger.info(msg);
238
- throw new Error(msg);
239
- }
240
- return true;
170
+ // Payment request doesn't have destinations - this shouldn't happen with new SDK
171
+ throw new Error(`ATXP: payment request does not contain destinations array`);
241
172
  };
242
173
  this.getPaymentRequestData = async (paymentRequestUrl) => {
243
174
  const prRequest = await this.sideChannelFetch(paymentRequestUrl);
@@ -245,6 +176,14 @@ class ATXPFetcher {
245
176
  throw new Error(`ATXP: GET ${paymentRequestUrl} failed: ${prRequest.status} ${prRequest.statusText}`);
246
177
  }
247
178
  const paymentRequest = await prRequest.json();
179
+ // Parse amount strings to BigNumber objects
180
+ if (paymentRequest.destinations) {
181
+ for (const dest of paymentRequest.destinations) {
182
+ if (typeof dest.amount === 'string' || typeof dest.amount === 'number') {
183
+ dest.amount = new BigNumber(dest.amount);
184
+ }
185
+ }
186
+ }
248
187
  return paymentRequest;
249
188
  };
250
189
  this.isAllowedAuthServer = (url) => {
@@ -258,15 +197,15 @@ class ATXPFetcher {
258
197
  throw new Error(`Code challenge not provided`);
259
198
  }
260
199
  if (!paymentMaker) {
261
- const availableNetworks = Array.from(this.paymentMakers.keys()).join(', ');
262
- throw new Error(`Payment maker is null/undefined. Available payment makers: [${availableNetworks}]. This usually indicates a payment maker object was not properly instantiated.`);
200
+ const paymentMakerCount = this.account.paymentMakers.length;
201
+ throw new Error(`Payment maker is null/undefined. Available payment maker count: ${paymentMakerCount}. This usually indicates a payment maker object was not properly instantiated.`);
263
202
  }
264
203
  // TypeScript should prevent this, but add runtime check for edge cases (untyped JS, version mismatches, etc.)
265
204
  if (!paymentMaker.generateJWT) {
266
- const availableNetworks = Array.from(this.paymentMakers.keys()).join(', ');
267
- throw new Error(`Payment maker is missing generateJWT method. Available payment makers: [${availableNetworks}]. This indicates the payment maker object does not implement the PaymentMaker interface. If using TypeScript, ensure your payment maker properly implements the PaymentMaker interface.`);
205
+ const paymentMakerCount = this.account.paymentMakers.length;
206
+ throw new Error(`Payment maker is missing generateJWT method. Available payment maker count: ${paymentMakerCount}. This indicates the payment maker object does not implement the PaymentMaker interface. If using TypeScript, ensure your payment maker properly implements the PaymentMaker interface.`);
268
207
  }
269
- const authToken = await paymentMaker.generateJWT({ paymentRequestId: '', codeChallenge: codeChallenge });
208
+ const authToken = await paymentMaker.generateJWT({ paymentRequestId: '', codeChallenge: codeChallenge, accountId: this.account.accountId });
270
209
  // Make a fetch call to the authorization URL with the payment ID
271
210
  // redirect=false is a hack
272
211
  // The OAuth spec calls for the authorization url to return with a redirect, but fetch
@@ -312,11 +251,11 @@ class ATXPFetcher {
312
251
  throw new Error(`Expected redirect response from authorization URL, got ${response.status}`);
313
252
  };
314
253
  this.authToService = async (error) => {
315
- // TODO: We need to generalize this - we can't assume that there's a single paymentMaker for the auth flow.
316
- if (this.paymentMakers.size > 1) {
254
+ // TODO: We need to generalize this - we can't assume that there's a single paymentMaker for the auth flow.
255
+ if (this.account.paymentMakers.length > 1) {
317
256
  throw new Error(`ATXP: multiple payment makers found - cannot determine which one to use for auth`);
318
257
  }
319
- const paymentMaker = Array.from(this.paymentMakers.values())[0];
258
+ const paymentMaker = this.account.paymentMakers[0];
320
259
  if (paymentMaker) {
321
260
  // We can do the full OAuth flow - we'll generate a signed JWT and call /authorize on the
322
261
  // AS to get a code, then exchange the code for an access token
@@ -331,14 +270,14 @@ class ATXPFetcher {
331
270
  // Call onAuthorize callback after successful authorization
332
271
  await this.onAuthorize({
333
272
  authorizationServer: authorizationUrl.origin,
334
- userId: this.accountId
273
+ userId: this.account.accountId
335
274
  });
336
275
  }
337
276
  catch (authError) {
338
277
  // Call onAuthorizeFailure callback if authorization fails
339
278
  await this.onAuthorizeFailure({
340
279
  authorizationServer: authorizationUrl.origin,
341
- userId: this.accountId,
280
+ userId: this.account.accountId,
342
281
  error: authError
343
282
  });
344
283
  throw authError;
@@ -349,13 +288,13 @@ class ATXPFetcher {
349
288
  // If we do, we'll use it to auth to the downstream resource
350
289
  // (In pass-through scenarios, the atxpServer() middleware stores the incoming
351
290
  // token in the DB under the '' resource URL).
352
- const existingToken = await this.db.getAccessToken(this.accountId, '');
291
+ const existingToken = await this.db.getAccessToken(this.account.accountId, '');
353
292
  if (!existingToken) {
354
293
  this.logger.info(`ATXP: no token found for the current server - we can't exchange a token if we don't have one`);
355
294
  throw error;
356
295
  }
357
296
  const newToken = await this.exchangeToken(existingToken, error.resourceServerUrl);
358
- this.db.saveAccessToken(this.accountId, error.resourceServerUrl, newToken);
297
+ this.db.saveAccessToken(this.account.accountId, error.resourceServerUrl, newToken);
359
298
  }
360
299
  };
361
300
  this.exchangeToken = async (myToken, newResourceUrl) => {
@@ -446,15 +385,15 @@ class ATXPFetcher {
446
385
  throw error;
447
386
  }
448
387
  };
449
- const { accountId, db, paymentMakers, fetchFn = fetch, sideChannelFetch = fetchFn, strict = true, allowInsecureRequests = process.env.NODE_ENV === 'development', allowedAuthorizationServers = [DEFAULT_AUTHORIZATION_SERVER], approvePayment = async () => true, logger = new ConsoleLogger(), onAuthorize = async () => { }, onAuthorizeFailure = async () => { }, onPayment = async () => { }, onPaymentFailure = async () => { } } = config;
388
+ const { account, db, destinationMakers, fetchFn = fetch, sideChannelFetch = fetchFn, strict = true, allowInsecureRequests = process.env.NODE_ENV === 'development', allowedAuthorizationServers = [DEFAULT_AUTHORIZATION_SERVER], approvePayment = async () => true, logger = new ConsoleLogger(), onAuthorize = async () => { }, onAuthorizeFailure = async () => { }, onPayment = async () => { }, onPaymentFailure = async () => { } } = config;
450
389
  // Use React Native safe fetch if in React Native environment
451
390
  const safeFetchFn = getIsReactNative() ? createReactNativeSafeFetch(fetchFn) : fetchFn;
452
391
  const safeSideChannelFetch = getIsReactNative() ? createReactNativeSafeFetch(sideChannelFetch) : sideChannelFetch;
453
- // ATXPClient should never actually use the callback url - instead of redirecting the user to
392
+ // ATXPClient should never actually use the callback url - instead of redirecting the user to
454
393
  // an authorization url which redirects back to the callback url, ATXPClient posts the payment
455
394
  // directly to the authorization server, then does the token exchange itself
456
395
  this.oauthClient = new OAuthClient({
457
- userId: accountId,
396
+ userId: account.accountId,
458
397
  db,
459
398
  callbackUrl: 'http://localhost:3000/unused-dummy-atxp-callback',
460
399
  isPublic: false,
@@ -464,10 +403,10 @@ class ATXPFetcher {
464
403
  allowInsecureRequests,
465
404
  logger: logger
466
405
  });
467
- this.paymentMakers = new Map(Object.entries(paymentMakers));
406
+ this.account = account;
407
+ this.destinationMakers = destinationMakers;
468
408
  this.sideChannelFetch = safeSideChannelFetch;
469
409
  this.db = db;
470
- this.accountId = accountId;
471
410
  this.allowedAuthorizationServers = allowedAuthorizationServers;
472
411
  this.approvePayment = approvePayment;
473
412
  this.logger = logger;
@@ -476,79 +415,6 @@ class ATXPFetcher {
476
415
  this.onPayment = onPayment;
477
416
  this.onPaymentFailure = onPaymentFailure || this.defaultPaymentFailureHandler;
478
417
  }
479
- /**
480
- * Resolves atxp_base or atxp_base_sepolia destinations to real base network destinations
481
- * by calling the payment_info endpoint to get the destination address and network
482
- */
483
- async resolveAtxpBaseDestination(network, paymentInfoUrl, paymentRequestId, amount, currency, receiver, memo) {
484
- // Check if this is an atxp_base network that needs resolution
485
- if (network !== 'atxp_base' && network !== 'atxp_base_sepolia') {
486
- return null;
487
- }
488
- // Map atxp_base networks to their real counterparts
489
- const realNetwork = network === 'atxp_base' ? 'base' : 'base_sepolia';
490
- // Get the payment maker for the real network
491
- const paymentMaker = this.paymentMakers.get(realNetwork);
492
- if (!paymentMaker) {
493
- this.logger.debug(`ATXP: payment network '${realNetwork}' not available for atxp_base resolution`);
494
- return null;
495
- }
496
- // Get the buyer address (source address) from the payment maker
497
- let buyerAddress;
498
- try {
499
- buyerAddress = await paymentMaker.getSourceAddress({
500
- amount,
501
- currency,
502
- receiver,
503
- memo
504
- });
505
- }
506
- catch (error) {
507
- this.logger.warn(`ATXP: failed to get source address from payment maker for ${realNetwork}: ${error.message}`);
508
- return null;
509
- }
510
- // Call the payment_info endpoint
511
- this.logger.debug(`ATXP: resolving ${network} destination via ${paymentInfoUrl}`);
512
- try {
513
- const response = await this.sideChannelFetch(paymentInfoUrl, {
514
- method: 'POST',
515
- headers: {
516
- 'Content-Type': 'application/json',
517
- },
518
- body: JSON.stringify({
519
- paymentRequestId,
520
- buyerAddress,
521
- }),
522
- });
523
- if (!response.ok) {
524
- const text = await response.text();
525
- this.logger.warn(`ATXP: payment_info endpoint failed: ${response.status} ${response.statusText} ${text}`);
526
- return null;
527
- }
528
- const data = await response.json();
529
- if (data.status !== 'success') {
530
- this.logger.warn(`ATXP: payment_info endpoint returned non-success status: ${JSON.stringify(data)}`);
531
- return null;
532
- }
533
- if (!data.destinationAddress) {
534
- this.logger.warn(`ATXP: payment_info endpoint did not return destinationAddress`);
535
- return null;
536
- }
537
- if (!data.network) {
538
- this.logger.warn(`ATXP: payment_info endpoint did not return network`);
539
- return null;
540
- }
541
- this.logger.info(`ATXP: resolved ${network} destination to ${data.destinationAddress} on ${data.network}`);
542
- return {
543
- destinationAddress: data.destinationAddress,
544
- network: data.network,
545
- };
546
- }
547
- catch (error) {
548
- this.logger.warn(`ATXP: failed to resolve ${network} destination: ${error.message}`);
549
- return null;
550
- }
551
- }
552
418
  }
553
419
 
554
420
  export { ATXPFetcher, atxpFetch };