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