@atxp/client 0.8.2 → 0.9.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/dist/index.d.ts CHANGED
@@ -1,12 +1,10 @@
1
- import { Account, Network, DestinationMaker, AuthorizationServerUrl, AccountId, Currency, OAuthDb, FetchLike, Logger, OAuthResourceClient, ClientCredentials, PKCEValues, AccessToken, PaymentMaker, Destination, PaymentIdentifier, Source, PaymentRequestOption } from '@atxp/common';
1
+ import { Account, Network, DestinationMaker, AuthorizationServerUrl, AccountId, Currency, OAuthDb, FetchLike, Logger, OAuthResourceClient, ClientCredentials, PKCEValues, AccessToken, PaymentRequestOption, Source, Destination } from '@atxp/common';
2
2
  export { ATXPAccount, Account, PaymentMaker } from '@atxp/common';
3
3
  import { ClientOptions, Client } from '@modelcontextprotocol/sdk/client/index.js';
4
4
  import { Implementation } from '@modelcontextprotocol/sdk/types.js';
5
5
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
6
6
  import * as oauth from 'oauth4webapi';
7
- import { ValidateTransferError as ValidateTransferError$1 } from '@solana/pay';
8
- import BigNumber$1 from 'bignumber.js';
9
- import { WalletClient, PublicActions, LocalAccount, Address, TypedData, Hex as Hex$1, SignableMessage, TransactionSerializable } from 'viem';
7
+ import { LocalAccount, Address, TypedData, Hex as Hex$1, SignableMessage, TransactionSerializable } from 'viem';
10
8
 
11
9
  type Hex = `0x${string}`;
12
10
  type AccountPrefix = Network;
@@ -125,66 +123,6 @@ declare class OAuthClient extends OAuthResourceClient {
125
123
  */
126
124
  declare function atxpFetch(config: ClientConfig): FetchLike;
127
125
 
128
- declare const ValidateTransferError: typeof ValidateTransferError$1;
129
- declare class SolanaPaymentMaker implements PaymentMaker {
130
- private connection;
131
- private source;
132
- private logger;
133
- constructor(solanaEndpoint: string, sourceSecretKey: string, logger?: Logger);
134
- getSourceAddress(_params: {
135
- amount: BigNumber$1;
136
- currency: Currency;
137
- receiver: string;
138
- memo: string;
139
- }): string;
140
- generateJWT: ({ paymentRequestId, codeChallenge, accountId }: {
141
- paymentRequestId: string;
142
- codeChallenge: string;
143
- accountId?: AccountId | null;
144
- }) => Promise<string>;
145
- makePayment: (destinations: Destination[], memo: string, _paymentRequestId?: string) => Promise<PaymentIdentifier | null>;
146
- }
147
-
148
- type ExtendedWalletClient = WalletClient & PublicActions;
149
- declare class BasePaymentMaker implements PaymentMaker {
150
- protected signingClient: ExtendedWalletClient;
151
- protected logger: Logger;
152
- constructor(baseRPCUrl: string, walletClient: WalletClient, logger?: Logger);
153
- getSourceAddress(_params: {
154
- amount: BigNumber;
155
- currency: Currency;
156
- receiver: string;
157
- memo: string;
158
- }): string;
159
- generateJWT({ paymentRequestId, codeChallenge, accountId }: {
160
- paymentRequestId: string;
161
- codeChallenge: string;
162
- accountId?: AccountId | null;
163
- }): Promise<string>;
164
- makePayment(destinations: Destination[], _memo: string, _paymentRequestId?: string): Promise<PaymentIdentifier | null>;
165
- }
166
-
167
- declare class SolanaAccount implements Account {
168
- accountId: AccountId;
169
- paymentMakers: PaymentMaker[];
170
- private sourcePublicKey;
171
- constructor(solanaEndpoint: string, sourceSecretKey: string);
172
- /**
173
- * Get sources for this account
174
- */
175
- getSources(): Promise<Source[]>;
176
- }
177
-
178
- declare const USDC_CONTRACT_ADDRESS_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
179
- declare const USDC_CONTRACT_ADDRESS_BASE_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
180
- /**
181
- * Get USDC contract address for Base chain by chain ID
182
- * @param chainId - Chain ID (8453 for mainnet, 84532 for sepolia)
183
- * @returns USDC contract address
184
- * @throws Error if chain ID is not supported
185
- */
186
- declare const getBaseUSDCAddress: (chainId: number) => string;
187
-
188
126
  /**
189
127
  * World Chain configuration type, compatible with viem's Chain interface
190
128
  */
@@ -291,23 +229,6 @@ declare const getPolygonByChainId: (chainId: number) => PolygonChain;
291
229
  */
292
230
  declare const getPolygonUSDCAddress: (chainId: number) => string;
293
231
 
294
- declare class BaseAccount implements Account {
295
- accountId: AccountId;
296
- paymentMakers: PaymentMaker[];
297
- private walletClient;
298
- private account;
299
- constructor(baseRPCUrl: string, sourceSecretKey: string);
300
- /**
301
- * Get the LocalAccount (signer) for this account.
302
- * This can be used with the x402 library or other signing operations.
303
- */
304
- getLocalAccount(): LocalAccount;
305
- /**
306
- * Get sources for this account
307
- */
308
- getSources(): Promise<Source[]>;
309
- }
310
-
311
232
  /**
312
233
  * ATXP implementation of viem's LocalAccount interface.
313
234
  * Delegates signing operations to the accounts-x402 API.
@@ -375,5 +296,5 @@ declare class PassthroughDestinationMaker implements DestinationMaker {
375
296
  makeDestinations(option: PaymentRequestOption, _logger: Logger, _paymentRequestId: string, _sources: Source[]): Promise<Destination[]>;
376
297
  }
377
298
 
378
- export { ATXPDestinationMaker, ATXPLocalAccount, BaseAccount, BasePaymentMaker, DEFAULT_CLIENT_CONFIG, InsufficientFundsError, OAuthAuthenticationRequiredError, OAuthClient, POLYGON_AMOY, POLYGON_MAINNET, PassthroughDestinationMaker, PaymentNetworkError, SolanaAccount, SolanaPaymentMaker, USDC_CONTRACT_ADDRESS_BASE, USDC_CONTRACT_ADDRESS_BASE_SEPOLIA, USDC_CONTRACT_ADDRESS_POLYGON_AMOY, USDC_CONTRACT_ADDRESS_POLYGON_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA, ValidateTransferError, WORLD_CHAIN_MAINNET, WORLD_CHAIN_SEPOLIA, atxpClient, atxpFetch, buildClientConfig, buildStreamableTransport, getBaseUSDCAddress, getPolygonAmoyWithRPC, getPolygonByChainId, getPolygonMainnetWithRPC, getPolygonUSDCAddress, getWorldChainByChainId, getWorldChainMainnetWithRPC, getWorldChainSepoliaWithRPC, getWorldChainUSDCAddress };
299
+ export { ATXPDestinationMaker, ATXPLocalAccount, DEFAULT_CLIENT_CONFIG, InsufficientFundsError, OAuthAuthenticationRequiredError, OAuthClient, POLYGON_AMOY, POLYGON_MAINNET, PassthroughDestinationMaker, PaymentNetworkError, USDC_CONTRACT_ADDRESS_POLYGON_AMOY, USDC_CONTRACT_ADDRESS_POLYGON_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA, WORLD_CHAIN_MAINNET, WORLD_CHAIN_SEPOLIA, atxpClient, atxpFetch, buildClientConfig, buildStreamableTransport, getPolygonAmoyWithRPC, getPolygonByChainId, getPolygonMainnetWithRPC, getPolygonUSDCAddress, getWorldChainByChainId, getWorldChainMainnetWithRPC, getWorldChainSepoliaWithRPC, getWorldChainUSDCAddress };
379
300
  export type { AccountIdString, ClientArgs, ClientConfig, FetchWrapper, Hex, OAuthClientConfig, PolygonChain, ProspectivePayment, WorldChain };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,UAAU,EACX,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,gCAAgC,EAChC,KAAK,iBAAiB,EACtB,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,SAAS,EACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,WAAW,EACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,0BAA0B,EAC1B,kCAAkC,EAClC,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,mCAAmC,EACnC,mCAAmC,EACnC,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,qCAAqC,EACrC,kCAAkC,EAClC,eAAe,EACf,YAAY,EACZ,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,KAAK,GAAG,EACR,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,EACxB,UAAU,EACX,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,gCAAgC,EAChC,KAAK,iBAAiB,EACtB,WAAW,EACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,SAAS,EACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,mCAAmC,EACnC,mCAAmC,EACnC,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,qCAAqC,EACrC,kCAAkC,EAClC,eAAe,EACf,YAAY,EACZ,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,KAAK,GAAG,EACR,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC"}
package/dist/index.js CHANGED
@@ -1,15 +1,7 @@
1
- import { crypto as crypto$1, OAuthResourceClient, ConsoleLogger, PAYMENT_REQUIRED_ERROR_CODE, isSSEResponse, parseMcpMessages, parsePaymentRequests, paymentRequiredError, DEFAULT_AUTHORIZATION_SERVER, getIsReactNative, createReactNativeSafeFetch, isEnumValue, ChainEnum, CurrencyEnum, NetworkEnum, assertNever, DEFAULT_ATXP_ACCOUNTS_SERVER, MemoryOAuthDb, ATXPAccount, generateJWT } from '@atxp/common';
1
+ import { crypto as crypto$1, OAuthResourceClient, ConsoleLogger, PAYMENT_REQUIRED_ERROR_CODE, isSSEResponse, parseMcpMessages, parsePaymentRequests, paymentRequiredError, DEFAULT_AUTHORIZATION_SERVER, getIsReactNative, createReactNativeSafeFetch, isEnumValue, ChainEnum, CurrencyEnum, NetworkEnum, assertNever, DEFAULT_ATXP_ACCOUNTS_SERVER, MemoryOAuthDb, ATXPAccount } from '@atxp/common';
2
2
  export { ATXPAccount } from '@atxp/common';
3
3
  import * as oauth from 'oauth4webapi';
4
- import BigNumber$1, { BigNumber } from 'bignumber.js';
5
- import { PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction, Connection, Keypair } from '@solana/web3.js';
6
- import { ValidateTransferError as ValidateTransferError$1, createTransfer } from '@solana/pay';
7
- import { getAssociatedTokenAddress, getAccount } from '@solana/spl-token';
8
- import bs58 from 'bs58';
9
- import { importJWK } from 'jose';
10
- import { publicActions, encodeFunctionData, parseEther, createWalletClient, http } from 'viem';
11
- import { base } from 'viem/chains';
12
- import { privateKeyToAccount } from 'viem/accounts';
4
+ import { BigNumber } from 'bignumber.js';
13
5
 
14
6
  class OAuthAuthenticationRequiredError extends Error {
15
7
  constructor(url, resourceServerUrl,
@@ -53,7 +45,8 @@ class OAuthClient extends OAuthResourceClient {
53
45
  strict,
54
46
  allowInsecureRequests,
55
47
  clientName,
56
- logger
48
+ logger,
49
+ registrationType: 'client'
57
50
  });
58
51
  this.extractResourceUrl = (response) => {
59
52
  if (response.status !== 401) {
@@ -348,16 +341,16 @@ class ATXPFetcher {
348
341
  this.logger.info(`PAYMENT FAILED: ${error.message}`);
349
342
  }
350
343
  };
351
- this.handleMultiDestinationPayment = async (paymentRequestData, paymentRequestUrl, paymentRequestId) => {
352
- if (!paymentRequestData.destinations || paymentRequestData.destinations.length === 0) {
344
+ this.handleMultiDestinationPayment = async (paymentRequest, paymentRequestUrl, paymentRequestId) => {
345
+ if (!paymentRequest.options || paymentRequest.options.length === 0) {
353
346
  return false;
354
347
  }
355
348
  // Get sources from the account
356
349
  const sources = await this.account.getSources();
357
- // Apply destination mappers to transform destinations
358
- // Convert PaymentRequestDestination[] to Destination[] for mapper compatibility
350
+ // Apply destination mappers to transform options
351
+ // Convert PaymentRequestOption[] to Destination[] for mapper compatibility
359
352
  const mappedDestinations = [];
360
- for (const option of paymentRequestData.destinations) {
353
+ for (const option of paymentRequest.options) {
361
354
  const destinationMaker = this.destinationMakers.get(option.network);
362
355
  if (!destinationMaker) {
363
356
  this.logger.debug(`ATXP: destination maker for network '${option.network}' not available, trying next destination`);
@@ -379,11 +372,11 @@ class ATXPFetcher {
379
372
  const firstDest = mappedDestinations[0];
380
373
  const prospectivePayment = {
381
374
  accountId: this.account.accountId,
382
- resourceUrl: paymentRequestData.resource?.toString() ?? '',
383
- resourceName: paymentRequestData.resourceName ?? '',
375
+ resourceUrl: paymentRequest.resource?.toString() ?? '',
376
+ resourceName: paymentRequest.payeeName ?? '',
384
377
  currency: firstDest.currency,
385
378
  amount: firstDest.amount,
386
- iss: paymentRequestData.iss ?? '',
379
+ iss: paymentRequest.payeeName ?? '',
387
380
  };
388
381
  // Ask for approval once for all payment attempts
389
382
  if (!await this.approvePayment(prospectivePayment)) {
@@ -396,7 +389,7 @@ class ATXPFetcher {
396
389
  for (const paymentMaker of this.account.paymentMakers) {
397
390
  try {
398
391
  // Pass all destinations to payment maker - it will filter and pick the one it can handle
399
- const result = await paymentMaker.makePayment(mappedDestinations, paymentRequestData.iss, paymentRequestId);
392
+ const result = await paymentMaker.makePayment(mappedDestinations, paymentRequest.payeeName ?? '', paymentRequestId);
400
393
  if (result === null) {
401
394
  this.logger.debug(`ATXP: payment maker cannot handle these destinations, trying next`);
402
395
  continue; // Try next payment maker
@@ -460,28 +453,28 @@ class ATXPFetcher {
460
453
  this.logger.info(`ATXP: payment requirement is not allowed on this server`);
461
454
  return false;
462
455
  }
463
- const paymentRequestData = await this.getPaymentRequestData(paymentRequestUrl);
464
- if (!paymentRequestData) {
456
+ const paymentRequest = await this.getPaymentRequest(paymentRequestUrl);
457
+ if (!paymentRequest) {
465
458
  throw new Error(`ATXP: payment request ${paymentRequestId} not found on server ${paymentRequestUrl}`);
466
459
  }
467
- // Handle multi-destination format
468
- if (paymentRequestData.destinations && paymentRequestData.destinations.length > 0) {
469
- return this.handleMultiDestinationPayment(paymentRequestData, paymentRequestUrl, paymentRequestId);
460
+ // Handle multi-option format
461
+ if (paymentRequest.options && paymentRequest.options.length > 0) {
462
+ return this.handleMultiDestinationPayment(paymentRequest, paymentRequestUrl, paymentRequestId);
470
463
  }
471
- // Payment request doesn't have destinations - this shouldn't happen with new SDK
472
- throw new Error(`ATXP: payment request does not contain destinations array`);
464
+ // Payment request doesn't have options - this shouldn't happen with new SDK
465
+ throw new Error(`ATXP: payment request does not contain options array`);
473
466
  };
474
- this.getPaymentRequestData = async (paymentRequestUrl) => {
467
+ this.getPaymentRequest = async (paymentRequestUrl) => {
475
468
  const prRequest = await this.sideChannelFetch(paymentRequestUrl);
476
469
  if (!prRequest.ok) {
477
470
  throw new Error(`ATXP: GET ${paymentRequestUrl} failed: ${prRequest.status} ${prRequest.statusText}`);
478
471
  }
479
472
  const paymentRequest = await prRequest.json();
480
473
  // Parse amount strings to BigNumber objects
481
- if (paymentRequest.destinations) {
482
- for (const dest of paymentRequest.destinations) {
483
- if (typeof dest.amount === 'string' || typeof dest.amount === 'number') {
484
- dest.amount = new BigNumber(dest.amount);
474
+ if (paymentRequest.options) {
475
+ for (const option of paymentRequest.options) {
476
+ if (typeof option.amount === 'string' || typeof option.amount === 'number') {
477
+ option.amount = new BigNumber(option.amount);
485
478
  }
486
479
  }
487
480
  }
@@ -16057,310 +16050,6 @@ async function atxpClient(args) {
16057
16050
  return client;
16058
16051
  }
16059
16052
 
16060
- // this is a global public key for USDC on the solana mainnet
16061
- const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
16062
- const ValidateTransferError = ValidateTransferError$1;
16063
- class SolanaPaymentMaker {
16064
- constructor(solanaEndpoint, sourceSecretKey, logger) {
16065
- this.generateJWT = async ({ paymentRequestId, codeChallenge, accountId }) => {
16066
- // Solana/Web3.js secretKey is 64 bytes:
16067
- // first 32 bytes are the private scalar, last 32 are the public key.
16068
- // JWK expects only the 32-byte private scalar for 'd'
16069
- const jwk = {
16070
- kty: 'OKP',
16071
- crv: 'Ed25519',
16072
- d: Buffer.from(this.source.secretKey.slice(0, 32)).toString('base64url'),
16073
- x: Buffer.from(this.source.publicKey.toBytes()).toString('base64url'),
16074
- };
16075
- const privateKey = await importJWK(jwk, 'EdDSA');
16076
- if (!(privateKey instanceof CryptoKey)) {
16077
- throw new Error('Expected CryptoKey from importJWK');
16078
- }
16079
- return generateJWT(this.source.publicKey.toBase58(), privateKey, paymentRequestId || '', codeChallenge || '', accountId);
16080
- };
16081
- this.makePayment = async (destinations, memo, _paymentRequestId) => {
16082
- // Filter to solana chain destinations
16083
- const solanaDestinations = destinations.filter(d => d.chain === 'solana');
16084
- if (solanaDestinations.length === 0) {
16085
- this.logger.debug('SolanaPaymentMaker: No solana destinations found, cannot handle payment');
16086
- return null; // Cannot handle these destinations
16087
- }
16088
- // Pick first solana destination
16089
- const dest = solanaDestinations[0];
16090
- const amount = dest.amount;
16091
- const currency = dest.currency;
16092
- const receiver = dest.address;
16093
- if (currency.toUpperCase() !== 'USDC') {
16094
- throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency);
16095
- }
16096
- const receiverKey = new PublicKey(receiver);
16097
- this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`);
16098
- try {
16099
- // Check balance before attempting payment
16100
- const tokenAccountAddress = await getAssociatedTokenAddress(USDC_MINT, this.source.publicKey);
16101
- const tokenAccount = await getAccount(this.connection, tokenAccountAddress);
16102
- const balance = new BigNumber$1(tokenAccount.amount.toString()).dividedBy(10 ** 6); // USDC has 6 decimals
16103
- if (balance.lt(amount)) {
16104
- this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`);
16105
- throw new InsufficientFundsError(currency, amount, balance, 'solana');
16106
- }
16107
- // Get the destination token account address (this will be the transactionId)
16108
- const destinationTokenAccount = await getAssociatedTokenAddress(USDC_MINT, receiverKey);
16109
- // Increase compute units to handle both memo and token transfer
16110
- // Memo uses ~6000 CUs, token transfer needs ~6500 CUs
16111
- const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
16112
- units: 50000,
16113
- });
16114
- const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({
16115
- microLamports: 20000,
16116
- });
16117
- const transaction = await createTransfer(this.connection, this.source.publicKey, {
16118
- amount: amount,
16119
- recipient: receiverKey,
16120
- splToken: USDC_MINT,
16121
- memo,
16122
- });
16123
- transaction.add(modifyComputeUnits);
16124
- transaction.add(addPriorityFee);
16125
- const transactionSignature = await sendAndConfirmTransaction(this.connection, transaction, [this.source]);
16126
- // Return transaction signature as transactionId and token account address as transactionSubId
16127
- return {
16128
- transactionId: transactionSignature,
16129
- transactionSubId: destinationTokenAccount.toBase58(),
16130
- chain: 'solana',
16131
- currency: 'USDC'
16132
- };
16133
- }
16134
- catch (error) {
16135
- if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) {
16136
- throw error;
16137
- }
16138
- // Wrap other errors in PaymentNetworkError
16139
- throw new PaymentNetworkError(`Payment failed on Solana network: ${error.message}`, error);
16140
- }
16141
- };
16142
- if (!solanaEndpoint) {
16143
- throw new Error('Solana endpoint is required');
16144
- }
16145
- if (!sourceSecretKey) {
16146
- throw new Error('Source secret key is required');
16147
- }
16148
- this.connection = new Connection(solanaEndpoint, { commitment: 'confirmed' });
16149
- this.source = Keypair.fromSecretKey(bs58.decode(sourceSecretKey));
16150
- this.logger = logger ?? new ConsoleLogger();
16151
- }
16152
- getSourceAddress(_params) {
16153
- return this.source.publicKey.toBase58();
16154
- }
16155
- }
16156
-
16157
- const USDC_CONTRACT_ADDRESS_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base mainnet
16158
- const USDC_CONTRACT_ADDRESS_BASE_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // USDC on Base Sepolia testnet
16159
- /**
16160
- * Get USDC contract address for Base chain by chain ID
16161
- * @param chainId - Chain ID (8453 for mainnet, 84532 for sepolia)
16162
- * @returns USDC contract address
16163
- * @throws Error if chain ID is not supported
16164
- */
16165
- const getBaseUSDCAddress = (chainId) => {
16166
- switch (chainId) {
16167
- case 8453: // Base mainnet
16168
- return USDC_CONTRACT_ADDRESS_BASE;
16169
- case 84532: // Base Sepolia
16170
- return USDC_CONTRACT_ADDRESS_BASE_SEPOLIA;
16171
- default:
16172
- throw new Error(`Unsupported Base Chain ID: ${chainId}. Supported chains: 8453 (mainnet), 84532 (sepolia)`);
16173
- }
16174
- };
16175
-
16176
- // Helper function to convert to base64url that works in both Node.js and browsers
16177
- function toBase64Url(data) {
16178
- // Convert string to base64
16179
- const base64 = typeof Buffer !== 'undefined'
16180
- ? Buffer.from(data).toString('base64')
16181
- : btoa(data);
16182
- // Convert base64 to base64url
16183
- return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
16184
- }
16185
- const USDC_DECIMALS = 6;
16186
- const ERC20_ABI = [
16187
- {
16188
- constant: false,
16189
- inputs: [
16190
- { name: "_to", type: "address" },
16191
- { name: "_value", type: "uint256" },
16192
- ],
16193
- name: "transfer",
16194
- outputs: [{ name: "", type: "bool" }],
16195
- type: "function",
16196
- },
16197
- {
16198
- "constant": true,
16199
- "inputs": [
16200
- {
16201
- "name": "_owner",
16202
- "type": "address"
16203
- }
16204
- ],
16205
- "name": "balanceOf",
16206
- "outputs": [
16207
- {
16208
- "name": "balance",
16209
- "type": "uint256"
16210
- }
16211
- ],
16212
- "payable": false,
16213
- "stateMutability": "view",
16214
- "type": "function"
16215
- }
16216
- ];
16217
- class BasePaymentMaker {
16218
- constructor(baseRPCUrl, walletClient, logger) {
16219
- if (!baseRPCUrl) {
16220
- throw new Error('baseRPCUrl was empty');
16221
- }
16222
- if (!walletClient) {
16223
- throw new Error('walletClient was empty');
16224
- }
16225
- if (!walletClient.account) {
16226
- throw new Error('walletClient.account was empty');
16227
- }
16228
- this.signingClient = walletClient.extend(publicActions);
16229
- this.logger = logger ?? new ConsoleLogger();
16230
- }
16231
- getSourceAddress(_params) {
16232
- return this.signingClient.account.address;
16233
- }
16234
- async generateJWT({ paymentRequestId, codeChallenge, accountId }) {
16235
- const headerObj = { alg: 'ES256K' };
16236
- const payloadObj = {
16237
- sub: this.signingClient.account.address,
16238
- iss: 'accounts.atxp.ai',
16239
- aud: 'https://auth.atxp.ai',
16240
- iat: Math.floor(Date.now() / 1000),
16241
- exp: Math.floor(Date.now() / 1000) + 60 * 60,
16242
- ...(codeChallenge ? { code_challenge: codeChallenge } : {}),
16243
- ...(paymentRequestId ? { payment_request_id: paymentRequestId } : {}),
16244
- ...(accountId ? { account_id: accountId } : {}),
16245
- };
16246
- const header = toBase64Url(JSON.stringify(headerObj));
16247
- const payload = toBase64Url(JSON.stringify(payloadObj));
16248
- const message = `${header}.${payload}`;
16249
- const messageBytes = typeof Buffer !== 'undefined'
16250
- ? Buffer.from(message, 'utf8')
16251
- : new TextEncoder().encode(message);
16252
- const signResult = await this.signingClient.signMessage({
16253
- account: this.signingClient.account,
16254
- message: { raw: messageBytes },
16255
- });
16256
- // For ES256K, signature is typically 65 bytes (r,s,v)
16257
- // Server expects the hex signature string (with 0x prefix) to be base64url encoded
16258
- // This creates: base64url("0x6eb2565...") not base64url(rawBytes)
16259
- // Pass the hex string directly to toBase64Url which will UTF-8 encode and base64url it
16260
- const signature = toBase64Url(signResult);
16261
- const jwt = `${header}.${payload}.${signature}`;
16262
- this.logger.info(`Generated ES256K JWT: ${jwt}`);
16263
- return jwt;
16264
- }
16265
- async makePayment(destinations, _memo, _paymentRequestId) {
16266
- // Filter to base chain destinations
16267
- const baseDestinations = destinations.filter(d => d.chain === 'base');
16268
- if (baseDestinations.length === 0) {
16269
- this.logger.debug('BasePaymentMaker: No base destinations found, cannot handle payment');
16270
- return null; // Cannot handle these destinations
16271
- }
16272
- // Pick first base destination
16273
- const dest = baseDestinations[0];
16274
- const amount = dest.amount;
16275
- const currency = dest.currency;
16276
- const receiver = dest.address;
16277
- if (currency.toUpperCase() !== 'USDC') {
16278
- throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency);
16279
- }
16280
- this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account.address}`);
16281
- try {
16282
- // Check balance before attempting payment
16283
- const balanceRaw = await this.signingClient.readContract({
16284
- address: USDC_CONTRACT_ADDRESS_BASE,
16285
- abi: ERC20_ABI,
16286
- functionName: 'balanceOf',
16287
- args: [this.signingClient.account.address],
16288
- });
16289
- const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS);
16290
- if (balance.lt(amount)) {
16291
- this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`);
16292
- throw new InsufficientFundsError(currency, amount, balance, 'base');
16293
- }
16294
- // Convert amount to USDC units (6 decimals) as BigInt
16295
- const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0));
16296
- const data = encodeFunctionData({
16297
- abi: ERC20_ABI,
16298
- functionName: "transfer",
16299
- args: [receiver, amountInUSDCUnits],
16300
- });
16301
- const hash = await this.signingClient.sendTransaction({
16302
- chain: base,
16303
- account: this.signingClient.account,
16304
- to: USDC_CONTRACT_ADDRESS_BASE,
16305
- data: data,
16306
- value: parseEther('0'),
16307
- maxPriorityFeePerGas: parseEther('0.000000001')
16308
- });
16309
- // Wait for transaction confirmation with more blocks to ensure propagation
16310
- this.logger.info(`Waiting for transaction confirmation: ${hash}`);
16311
- const receipt = await this.signingClient.waitForTransactionReceipt({
16312
- hash: hash,
16313
- confirmations: 1
16314
- });
16315
- if (receipt.status === 'reverted') {
16316
- throw new PaymentNetworkError(`Transaction reverted: ${hash}`, new Error('Transaction reverted on chain'));
16317
- }
16318
- this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`);
16319
- // Return payment result with chain and currency
16320
- return {
16321
- transactionId: hash,
16322
- chain: 'base',
16323
- currency: 'USDC'
16324
- };
16325
- }
16326
- catch (error) {
16327
- if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) {
16328
- throw error;
16329
- }
16330
- // Wrap other errors in PaymentNetworkError
16331
- throw new PaymentNetworkError(`Payment failed on Base network: ${error.message}`, error);
16332
- }
16333
- }
16334
- }
16335
-
16336
- class SolanaAccount {
16337
- constructor(solanaEndpoint, sourceSecretKey) {
16338
- if (!solanaEndpoint) {
16339
- throw new Error('Solana endpoint is required');
16340
- }
16341
- if (!sourceSecretKey) {
16342
- throw new Error('Source secret key is required');
16343
- }
16344
- const source = Keypair.fromSecretKey(bs58.decode(sourceSecretKey));
16345
- this.sourcePublicKey = source.publicKey.toBase58();
16346
- // Format accountId as network:address
16347
- this.accountId = `solana:${this.sourcePublicKey}`;
16348
- this.paymentMakers = [
16349
- new SolanaPaymentMaker(solanaEndpoint, sourceSecretKey)
16350
- ];
16351
- }
16352
- /**
16353
- * Get sources for this account
16354
- */
16355
- async getSources() {
16356
- return [{
16357
- address: this.sourcePublicKey,
16358
- chain: 'solana',
16359
- walletType: 'eoa'
16360
- }];
16361
- }
16362
- }
16363
-
16364
16053
  const USDC_CONTRACT_ADDRESS_WORLD_MAINNET = "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"; // USDC.e on World Chain mainnet
16365
16054
  const USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA = "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"; // USDC.e on World Chain Sepolia (placeholder - update with actual address)
16366
16055
  // World Chain Mainnet (Chain ID: 480)
@@ -16523,45 +16212,6 @@ const getPolygonUSDCAddress = (chainId) => {
16523
16212
  }
16524
16213
  };
16525
16214
 
16526
- class BaseAccount {
16527
- constructor(baseRPCUrl, sourceSecretKey) {
16528
- if (!baseRPCUrl) {
16529
- throw new Error('Base RPC URL is required');
16530
- }
16531
- if (!sourceSecretKey) {
16532
- throw new Error('Source secret key is required');
16533
- }
16534
- this.account = privateKeyToAccount(sourceSecretKey);
16535
- // Format accountId as network:address
16536
- this.accountId = `base:${this.account.address}`;
16537
- this.walletClient = createWalletClient({
16538
- account: this.account,
16539
- chain: base,
16540
- transport: http(baseRPCUrl),
16541
- });
16542
- this.paymentMakers = [
16543
- new BasePaymentMaker(baseRPCUrl, this.walletClient)
16544
- ];
16545
- }
16546
- /**
16547
- * Get the LocalAccount (signer) for this account.
16548
- * This can be used with the x402 library or other signing operations.
16549
- */
16550
- getLocalAccount() {
16551
- return this.account;
16552
- }
16553
- /**
16554
- * Get sources for this account
16555
- */
16556
- async getSources() {
16557
- return [{
16558
- address: this.account.address,
16559
- chain: 'base',
16560
- walletType: 'eoa'
16561
- }];
16562
- }
16563
- }
16564
-
16565
16215
  function toBasicAuth(token) {
16566
16216
  // Basic auth is base64("username:password"), password is blank
16567
16217
  const b64 = Buffer.from(`${token}:`).toString('base64');
@@ -16662,5 +16312,5 @@ class ATXPLocalAccount {
16662
16312
  }
16663
16313
  }
16664
16314
 
16665
- export { ATXPDestinationMaker, ATXPLocalAccount, BaseAccount, BasePaymentMaker, DEFAULT_CLIENT_CONFIG, InsufficientFundsError, OAuthAuthenticationRequiredError, OAuthClient, POLYGON_AMOY, POLYGON_MAINNET, PassthroughDestinationMaker, PaymentNetworkError, SolanaAccount, SolanaPaymentMaker, USDC_CONTRACT_ADDRESS_BASE, USDC_CONTRACT_ADDRESS_BASE_SEPOLIA, USDC_CONTRACT_ADDRESS_POLYGON_AMOY, USDC_CONTRACT_ADDRESS_POLYGON_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA, ValidateTransferError, WORLD_CHAIN_MAINNET, WORLD_CHAIN_SEPOLIA, atxpClient, atxpFetch, buildClientConfig, buildStreamableTransport, getBaseUSDCAddress, getPolygonAmoyWithRPC, getPolygonByChainId, getPolygonMainnetWithRPC, getPolygonUSDCAddress, getWorldChainByChainId, getWorldChainMainnetWithRPC, getWorldChainSepoliaWithRPC, getWorldChainUSDCAddress };
16315
+ export { ATXPDestinationMaker, ATXPLocalAccount, DEFAULT_CLIENT_CONFIG, InsufficientFundsError, OAuthAuthenticationRequiredError, OAuthClient, POLYGON_AMOY, POLYGON_MAINNET, PassthroughDestinationMaker, PaymentNetworkError, USDC_CONTRACT_ADDRESS_POLYGON_AMOY, USDC_CONTRACT_ADDRESS_POLYGON_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_MAINNET, USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA, WORLD_CHAIN_MAINNET, WORLD_CHAIN_SEPOLIA, atxpClient, atxpFetch, buildClientConfig, buildStreamableTransport, getPolygonAmoyWithRPC, getPolygonByChainId, getPolygonMainnetWithRPC, getPolygonUSDCAddress, getWorldChainByChainId, getWorldChainMainnetWithRPC, getWorldChainSepoliaWithRPC, getWorldChainUSDCAddress };
16666
16316
  //# sourceMappingURL=index.js.map