@atxp/client 0.8.3 → 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.cjs CHANGED
@@ -2,15 +2,7 @@
2
2
 
3
3
  var common = require('@atxp/common');
4
4
  var oauth = require('oauth4webapi');
5
- var BigNumber = require('bignumber.js');
6
- var web3_js = require('@solana/web3.js');
7
- var pay = require('@solana/pay');
8
- var splToken = require('@solana/spl-token');
9
- var bs58 = require('bs58');
10
- var jose = require('jose');
11
- var viem = require('viem');
12
- var chains = require('viem/chains');
13
- var accounts = require('viem/accounts');
5
+ var bignumber_js = require('bignumber.js');
14
6
 
15
7
  function _interopNamespaceDefault(e) {
16
8
  var n = Object.create(null);
@@ -502,7 +494,7 @@ class ATXPFetcher {
502
494
  if (paymentRequest.options) {
503
495
  for (const option of paymentRequest.options) {
504
496
  if (typeof option.amount === 'string' || typeof option.amount === 'number') {
505
- option.amount = new BigNumber.BigNumber(option.amount);
497
+ option.amount = new bignumber_js.BigNumber(option.amount);
506
498
  }
507
499
  }
508
500
  }
@@ -15862,7 +15854,7 @@ function parseDestinationsResponse(data) {
15862
15854
  throw new Error(`Invalid destination at index ${index}: currency "${dest.currency}" is not a valid currency. Valid currencies are: ${validCurrencies}`);
15863
15855
  }
15864
15856
  // Validate amount is a valid number
15865
- const amount = new BigNumber.BigNumber(dest.amount);
15857
+ const amount = new bignumber_js.BigNumber(dest.amount);
15866
15858
  if (amount.isNaN()) {
15867
15859
  throw new Error(`Invalid destination at index ${index}: amount "${dest.amount}" is not a valid number`);
15868
15860
  }
@@ -16078,310 +16070,6 @@ async function atxpClient(args) {
16078
16070
  return client;
16079
16071
  }
16080
16072
 
16081
- // this is a global public key for USDC on the solana mainnet
16082
- const USDC_MINT = new web3_js.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
16083
- const ValidateTransferError = pay.ValidateTransferError;
16084
- class SolanaPaymentMaker {
16085
- constructor(solanaEndpoint, sourceSecretKey, logger) {
16086
- this.generateJWT = async ({ paymentRequestId, codeChallenge, accountId }) => {
16087
- // Solana/Web3.js secretKey is 64 bytes:
16088
- // first 32 bytes are the private scalar, last 32 are the public key.
16089
- // JWK expects only the 32-byte private scalar for 'd'
16090
- const jwk = {
16091
- kty: 'OKP',
16092
- crv: 'Ed25519',
16093
- d: Buffer.from(this.source.secretKey.slice(0, 32)).toString('base64url'),
16094
- x: Buffer.from(this.source.publicKey.toBytes()).toString('base64url'),
16095
- };
16096
- const privateKey = await jose.importJWK(jwk, 'EdDSA');
16097
- if (!(privateKey instanceof CryptoKey)) {
16098
- throw new Error('Expected CryptoKey from importJWK');
16099
- }
16100
- return common.generateJWT(this.source.publicKey.toBase58(), privateKey, paymentRequestId || '', codeChallenge || '', accountId);
16101
- };
16102
- this.makePayment = async (destinations, memo, _paymentRequestId) => {
16103
- // Filter to solana chain destinations
16104
- const solanaDestinations = destinations.filter(d => d.chain === 'solana');
16105
- if (solanaDestinations.length === 0) {
16106
- this.logger.debug('SolanaPaymentMaker: No solana destinations found, cannot handle payment');
16107
- return null; // Cannot handle these destinations
16108
- }
16109
- // Pick first solana destination
16110
- const dest = solanaDestinations[0];
16111
- const amount = dest.amount;
16112
- const currency = dest.currency;
16113
- const receiver = dest.address;
16114
- if (currency.toUpperCase() !== 'USDC') {
16115
- throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency);
16116
- }
16117
- const receiverKey = new web3_js.PublicKey(receiver);
16118
- this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`);
16119
- try {
16120
- // Check balance before attempting payment
16121
- const tokenAccountAddress = await splToken.getAssociatedTokenAddress(USDC_MINT, this.source.publicKey);
16122
- const tokenAccount = await splToken.getAccount(this.connection, tokenAccountAddress);
16123
- const balance = new BigNumber(tokenAccount.amount.toString()).dividedBy(10 ** 6); // USDC has 6 decimals
16124
- if (balance.lt(amount)) {
16125
- this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`);
16126
- throw new InsufficientFundsError(currency, amount, balance, 'solana');
16127
- }
16128
- // Get the destination token account address (this will be the transactionId)
16129
- const destinationTokenAccount = await splToken.getAssociatedTokenAddress(USDC_MINT, receiverKey);
16130
- // Increase compute units to handle both memo and token transfer
16131
- // Memo uses ~6000 CUs, token transfer needs ~6500 CUs
16132
- const modifyComputeUnits = web3_js.ComputeBudgetProgram.setComputeUnitLimit({
16133
- units: 50000,
16134
- });
16135
- const addPriorityFee = web3_js.ComputeBudgetProgram.setComputeUnitPrice({
16136
- microLamports: 20000,
16137
- });
16138
- const transaction = await pay.createTransfer(this.connection, this.source.publicKey, {
16139
- amount: amount,
16140
- recipient: receiverKey,
16141
- splToken: USDC_MINT,
16142
- memo,
16143
- });
16144
- transaction.add(modifyComputeUnits);
16145
- transaction.add(addPriorityFee);
16146
- const transactionSignature = await web3_js.sendAndConfirmTransaction(this.connection, transaction, [this.source]);
16147
- // Return transaction signature as transactionId and token account address as transactionSubId
16148
- return {
16149
- transactionId: transactionSignature,
16150
- transactionSubId: destinationTokenAccount.toBase58(),
16151
- chain: 'solana',
16152
- currency: 'USDC'
16153
- };
16154
- }
16155
- catch (error) {
16156
- if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) {
16157
- throw error;
16158
- }
16159
- // Wrap other errors in PaymentNetworkError
16160
- throw new PaymentNetworkError(`Payment failed on Solana network: ${error.message}`, error);
16161
- }
16162
- };
16163
- if (!solanaEndpoint) {
16164
- throw new Error('Solana endpoint is required');
16165
- }
16166
- if (!sourceSecretKey) {
16167
- throw new Error('Source secret key is required');
16168
- }
16169
- this.connection = new web3_js.Connection(solanaEndpoint, { commitment: 'confirmed' });
16170
- this.source = web3_js.Keypair.fromSecretKey(bs58.decode(sourceSecretKey));
16171
- this.logger = logger ?? new common.ConsoleLogger();
16172
- }
16173
- getSourceAddress(_params) {
16174
- return this.source.publicKey.toBase58();
16175
- }
16176
- }
16177
-
16178
- const USDC_CONTRACT_ADDRESS_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base mainnet
16179
- const USDC_CONTRACT_ADDRESS_BASE_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // USDC on Base Sepolia testnet
16180
- /**
16181
- * Get USDC contract address for Base chain by chain ID
16182
- * @param chainId - Chain ID (8453 for mainnet, 84532 for sepolia)
16183
- * @returns USDC contract address
16184
- * @throws Error if chain ID is not supported
16185
- */
16186
- const getBaseUSDCAddress = (chainId) => {
16187
- switch (chainId) {
16188
- case 8453: // Base mainnet
16189
- return USDC_CONTRACT_ADDRESS_BASE;
16190
- case 84532: // Base Sepolia
16191
- return USDC_CONTRACT_ADDRESS_BASE_SEPOLIA;
16192
- default:
16193
- throw new Error(`Unsupported Base Chain ID: ${chainId}. Supported chains: 8453 (mainnet), 84532 (sepolia)`);
16194
- }
16195
- };
16196
-
16197
- // Helper function to convert to base64url that works in both Node.js and browsers
16198
- function toBase64Url(data) {
16199
- // Convert string to base64
16200
- const base64 = typeof Buffer !== 'undefined'
16201
- ? Buffer.from(data).toString('base64')
16202
- : btoa(data);
16203
- // Convert base64 to base64url
16204
- return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
16205
- }
16206
- const USDC_DECIMALS = 6;
16207
- const ERC20_ABI = [
16208
- {
16209
- constant: false,
16210
- inputs: [
16211
- { name: "_to", type: "address" },
16212
- { name: "_value", type: "uint256" },
16213
- ],
16214
- name: "transfer",
16215
- outputs: [{ name: "", type: "bool" }],
16216
- type: "function",
16217
- },
16218
- {
16219
- "constant": true,
16220
- "inputs": [
16221
- {
16222
- "name": "_owner",
16223
- "type": "address"
16224
- }
16225
- ],
16226
- "name": "balanceOf",
16227
- "outputs": [
16228
- {
16229
- "name": "balance",
16230
- "type": "uint256"
16231
- }
16232
- ],
16233
- "payable": false,
16234
- "stateMutability": "view",
16235
- "type": "function"
16236
- }
16237
- ];
16238
- class BasePaymentMaker {
16239
- constructor(baseRPCUrl, walletClient, logger) {
16240
- if (!baseRPCUrl) {
16241
- throw new Error('baseRPCUrl was empty');
16242
- }
16243
- if (!walletClient) {
16244
- throw new Error('walletClient was empty');
16245
- }
16246
- if (!walletClient.account) {
16247
- throw new Error('walletClient.account was empty');
16248
- }
16249
- this.signingClient = walletClient.extend(viem.publicActions);
16250
- this.logger = logger ?? new common.ConsoleLogger();
16251
- }
16252
- getSourceAddress(_params) {
16253
- return this.signingClient.account.address;
16254
- }
16255
- async generateJWT({ paymentRequestId, codeChallenge, accountId }) {
16256
- const headerObj = { alg: 'ES256K' };
16257
- const payloadObj = {
16258
- sub: this.signingClient.account.address,
16259
- iss: 'accounts.atxp.ai',
16260
- aud: 'https://auth.atxp.ai',
16261
- iat: Math.floor(Date.now() / 1000),
16262
- exp: Math.floor(Date.now() / 1000) + 60 * 60,
16263
- ...(codeChallenge ? { code_challenge: codeChallenge } : {}),
16264
- ...(paymentRequestId ? { payment_request_id: paymentRequestId } : {}),
16265
- ...(accountId ? { account_id: accountId } : {}),
16266
- };
16267
- const header = toBase64Url(JSON.stringify(headerObj));
16268
- const payload = toBase64Url(JSON.stringify(payloadObj));
16269
- const message = `${header}.${payload}`;
16270
- const messageBytes = typeof Buffer !== 'undefined'
16271
- ? Buffer.from(message, 'utf8')
16272
- : new TextEncoder().encode(message);
16273
- const signResult = await this.signingClient.signMessage({
16274
- account: this.signingClient.account,
16275
- message: { raw: messageBytes },
16276
- });
16277
- // For ES256K, signature is typically 65 bytes (r,s,v)
16278
- // Server expects the hex signature string (with 0x prefix) to be base64url encoded
16279
- // This creates: base64url("0x6eb2565...") not base64url(rawBytes)
16280
- // Pass the hex string directly to toBase64Url which will UTF-8 encode and base64url it
16281
- const signature = toBase64Url(signResult);
16282
- const jwt = `${header}.${payload}.${signature}`;
16283
- this.logger.info(`Generated ES256K JWT: ${jwt}`);
16284
- return jwt;
16285
- }
16286
- async makePayment(destinations, _memo, _paymentRequestId) {
16287
- // Filter to base chain destinations
16288
- const baseDestinations = destinations.filter(d => d.chain === 'base');
16289
- if (baseDestinations.length === 0) {
16290
- this.logger.debug('BasePaymentMaker: No base destinations found, cannot handle payment');
16291
- return null; // Cannot handle these destinations
16292
- }
16293
- // Pick first base destination
16294
- const dest = baseDestinations[0];
16295
- const amount = dest.amount;
16296
- const currency = dest.currency;
16297
- const receiver = dest.address;
16298
- if (currency.toUpperCase() !== 'USDC') {
16299
- throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency);
16300
- }
16301
- this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account.address}`);
16302
- try {
16303
- // Check balance before attempting payment
16304
- const balanceRaw = await this.signingClient.readContract({
16305
- address: USDC_CONTRACT_ADDRESS_BASE,
16306
- abi: ERC20_ABI,
16307
- functionName: 'balanceOf',
16308
- args: [this.signingClient.account.address],
16309
- });
16310
- const balance = new BigNumber.BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS);
16311
- if (balance.lt(amount)) {
16312
- this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`);
16313
- throw new InsufficientFundsError(currency, amount, balance, 'base');
16314
- }
16315
- // Convert amount to USDC units (6 decimals) as BigInt
16316
- const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0));
16317
- const data = viem.encodeFunctionData({
16318
- abi: ERC20_ABI,
16319
- functionName: "transfer",
16320
- args: [receiver, amountInUSDCUnits],
16321
- });
16322
- const hash = await this.signingClient.sendTransaction({
16323
- chain: chains.base,
16324
- account: this.signingClient.account,
16325
- to: USDC_CONTRACT_ADDRESS_BASE,
16326
- data: data,
16327
- value: viem.parseEther('0'),
16328
- maxPriorityFeePerGas: viem.parseEther('0.000000001')
16329
- });
16330
- // Wait for transaction confirmation with more blocks to ensure propagation
16331
- this.logger.info(`Waiting for transaction confirmation: ${hash}`);
16332
- const receipt = await this.signingClient.waitForTransactionReceipt({
16333
- hash: hash,
16334
- confirmations: 1
16335
- });
16336
- if (receipt.status === 'reverted') {
16337
- throw new PaymentNetworkError(`Transaction reverted: ${hash}`, new Error('Transaction reverted on chain'));
16338
- }
16339
- this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`);
16340
- // Return payment result with chain and currency
16341
- return {
16342
- transactionId: hash,
16343
- chain: 'base',
16344
- currency: 'USDC'
16345
- };
16346
- }
16347
- catch (error) {
16348
- if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) {
16349
- throw error;
16350
- }
16351
- // Wrap other errors in PaymentNetworkError
16352
- throw new PaymentNetworkError(`Payment failed on Base network: ${error.message}`, error);
16353
- }
16354
- }
16355
- }
16356
-
16357
- class SolanaAccount {
16358
- constructor(solanaEndpoint, sourceSecretKey) {
16359
- if (!solanaEndpoint) {
16360
- throw new Error('Solana endpoint is required');
16361
- }
16362
- if (!sourceSecretKey) {
16363
- throw new Error('Source secret key is required');
16364
- }
16365
- const source = web3_js.Keypair.fromSecretKey(bs58.decode(sourceSecretKey));
16366
- this.sourcePublicKey = source.publicKey.toBase58();
16367
- // Format accountId as network:address
16368
- this.accountId = `solana:${this.sourcePublicKey}`;
16369
- this.paymentMakers = [
16370
- new SolanaPaymentMaker(solanaEndpoint, sourceSecretKey)
16371
- ];
16372
- }
16373
- /**
16374
- * Get sources for this account
16375
- */
16376
- async getSources() {
16377
- return [{
16378
- address: this.sourcePublicKey,
16379
- chain: 'solana',
16380
- walletType: 'eoa'
16381
- }];
16382
- }
16383
- }
16384
-
16385
16073
  const USDC_CONTRACT_ADDRESS_WORLD_MAINNET = "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"; // USDC.e on World Chain mainnet
16386
16074
  const USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA = "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"; // USDC.e on World Chain Sepolia (placeholder - update with actual address)
16387
16075
  // World Chain Mainnet (Chain ID: 480)
@@ -16544,45 +16232,6 @@ const getPolygonUSDCAddress = (chainId) => {
16544
16232
  }
16545
16233
  };
16546
16234
 
16547
- class BaseAccount {
16548
- constructor(baseRPCUrl, sourceSecretKey) {
16549
- if (!baseRPCUrl) {
16550
- throw new Error('Base RPC URL is required');
16551
- }
16552
- if (!sourceSecretKey) {
16553
- throw new Error('Source secret key is required');
16554
- }
16555
- this.account = accounts.privateKeyToAccount(sourceSecretKey);
16556
- // Format accountId as network:address
16557
- this.accountId = `base:${this.account.address}`;
16558
- this.walletClient = viem.createWalletClient({
16559
- account: this.account,
16560
- chain: chains.base,
16561
- transport: viem.http(baseRPCUrl),
16562
- });
16563
- this.paymentMakers = [
16564
- new BasePaymentMaker(baseRPCUrl, this.walletClient)
16565
- ];
16566
- }
16567
- /**
16568
- * Get the LocalAccount (signer) for this account.
16569
- * This can be used with the x402 library or other signing operations.
16570
- */
16571
- getLocalAccount() {
16572
- return this.account;
16573
- }
16574
- /**
16575
- * Get sources for this account
16576
- */
16577
- async getSources() {
16578
- return [{
16579
- address: this.account.address,
16580
- chain: 'base',
16581
- walletType: 'eoa'
16582
- }];
16583
- }
16584
- }
16585
-
16586
16235
  function toBasicAuth(token) {
16587
16236
  // Basic auth is base64("username:password"), password is blank
16588
16237
  const b64 = Buffer.from(`${token}:`).toString('base64');
@@ -16689,8 +16338,6 @@ Object.defineProperty(exports, "ATXPAccount", {
16689
16338
  });
16690
16339
  exports.ATXPDestinationMaker = ATXPDestinationMaker;
16691
16340
  exports.ATXPLocalAccount = ATXPLocalAccount;
16692
- exports.BaseAccount = BaseAccount;
16693
- exports.BasePaymentMaker = BasePaymentMaker;
16694
16341
  exports.DEFAULT_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG;
16695
16342
  exports.InsufficientFundsError = InsufficientFundsError;
16696
16343
  exports.OAuthAuthenticationRequiredError = OAuthAuthenticationRequiredError;
@@ -16699,22 +16346,16 @@ exports.POLYGON_AMOY = POLYGON_AMOY;
16699
16346
  exports.POLYGON_MAINNET = POLYGON_MAINNET;
16700
16347
  exports.PassthroughDestinationMaker = PassthroughDestinationMaker;
16701
16348
  exports.PaymentNetworkError = PaymentNetworkError;
16702
- exports.SolanaAccount = SolanaAccount;
16703
- exports.SolanaPaymentMaker = SolanaPaymentMaker;
16704
- exports.USDC_CONTRACT_ADDRESS_BASE = USDC_CONTRACT_ADDRESS_BASE;
16705
- exports.USDC_CONTRACT_ADDRESS_BASE_SEPOLIA = USDC_CONTRACT_ADDRESS_BASE_SEPOLIA;
16706
16349
  exports.USDC_CONTRACT_ADDRESS_POLYGON_AMOY = USDC_CONTRACT_ADDRESS_POLYGON_AMOY;
16707
16350
  exports.USDC_CONTRACT_ADDRESS_POLYGON_MAINNET = USDC_CONTRACT_ADDRESS_POLYGON_MAINNET;
16708
16351
  exports.USDC_CONTRACT_ADDRESS_WORLD_MAINNET = USDC_CONTRACT_ADDRESS_WORLD_MAINNET;
16709
16352
  exports.USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA = USDC_CONTRACT_ADDRESS_WORLD_SEPOLIA;
16710
- exports.ValidateTransferError = ValidateTransferError;
16711
16353
  exports.WORLD_CHAIN_MAINNET = WORLD_CHAIN_MAINNET;
16712
16354
  exports.WORLD_CHAIN_SEPOLIA = WORLD_CHAIN_SEPOLIA;
16713
16355
  exports.atxpClient = atxpClient;
16714
16356
  exports.atxpFetch = atxpFetch;
16715
16357
  exports.buildClientConfig = buildClientConfig;
16716
16358
  exports.buildStreamableTransport = buildStreamableTransport;
16717
- exports.getBaseUSDCAddress = getBaseUSDCAddress;
16718
16359
  exports.getPolygonAmoyWithRPC = getPolygonAmoyWithRPC;
16719
16360
  exports.getPolygonByChainId = getPolygonByChainId;
16720
16361
  exports.getPolygonMainnetWithRPC = getPolygonMainnetWithRPC;