facinet 2.3.0 → 2.4.2
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/README.md +213 -41
- package/dist/browser.js +47 -13
- package/dist/browser.js.map +2 -2
- package/dist/commands/facilitator.d.ts.map +1 -1
- package/dist/commands/facilitator.js +16 -8
- package/dist/commands/facilitator.js.map +1 -1
- package/dist/commands/pay.d.ts.map +1 -1
- package/dist/commands/pay.js +12 -5
- package/dist/commands/pay.js.map +1 -1
- package/dist/index.js +55 -32
- package/dist/index.js.map +2 -2
- package/dist/sdk/Facinet.d.ts +2 -2
- package/dist/sdk/Facinet.d.ts.map +1 -1
- package/dist/sdk/Facinet.js +52 -10
- package/dist/sdk/Facinet.js.map +1 -1
- package/dist/sdk/types.d.ts +1 -1
- package/dist/sdk.js +47 -13
- package/dist/sdk.js.map +2 -2
- package/dist/sdk.mjs +47 -13
- package/dist/sdk.mjs.map +2 -2
- package/dist/utils/api.d.ts +6 -2
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +29 -8
- package/dist/utils/api.js.map +1 -1
- package/package.json +1 -1
package/dist/sdk.mjs
CHANGED
|
@@ -57,13 +57,20 @@ var NETWORK_ALIASES = {
|
|
|
57
57
|
"polygon": "polygon-amoy",
|
|
58
58
|
"base": "base-sepolia"
|
|
59
59
|
};
|
|
60
|
+
var DEFAULT_API_URL = "https://facinet.vercel.app";
|
|
60
61
|
function resolveNetwork(network) {
|
|
61
62
|
return NETWORK_ALIASES[network] || network;
|
|
62
63
|
}
|
|
64
|
+
function getApiUrlForNetwork(network, customApiUrl) {
|
|
65
|
+
if (customApiUrl) {
|
|
66
|
+
return customApiUrl.replace(/\/$/, "");
|
|
67
|
+
}
|
|
68
|
+
return DEFAULT_API_URL;
|
|
69
|
+
}
|
|
63
70
|
var Facinet = class _Facinet {
|
|
64
71
|
constructor(config = {}) {
|
|
65
|
-
const apiUrl = (config.apiUrl || "https://x402-avalanche-chi.vercel.app").replace(/\/$/, "");
|
|
66
72
|
const resolvedNetwork = resolveNetwork(config.network || "avalanche-fuji");
|
|
73
|
+
const apiUrl = getApiUrlForNetwork(resolvedNetwork, config.apiUrl);
|
|
67
74
|
this.config = {
|
|
68
75
|
apiUrl,
|
|
69
76
|
privateKey: config.privateKey || "",
|
|
@@ -234,7 +241,7 @@ var Facinet = class _Facinet {
|
|
|
234
241
|
txHash: response.data.txHash,
|
|
235
242
|
facilitator: {
|
|
236
243
|
id: facilitator.id,
|
|
237
|
-
name: facilitator.name,
|
|
244
|
+
name: facilitator.name || `Facilitator ${facilitator.id.slice(0, 8)}`,
|
|
238
245
|
wallet: facilitator.facilitatorWallet
|
|
239
246
|
},
|
|
240
247
|
payment: {
|
|
@@ -253,29 +260,56 @@ var Facinet = class _Facinet {
|
|
|
253
260
|
}
|
|
254
261
|
}
|
|
255
262
|
/**
|
|
256
|
-
* Get all active facilitators
|
|
263
|
+
* Get all active facilitators for the current network
|
|
257
264
|
*/
|
|
258
265
|
async getFacilitators() {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
266
|
+
try {
|
|
267
|
+
const response = await axios.get(
|
|
268
|
+
`${this.config.apiUrl}/api/facilitator/list`,
|
|
269
|
+
{
|
|
270
|
+
timeout: 1e4,
|
|
271
|
+
headers: {
|
|
272
|
+
"User-Agent": "Facinet-SDK/2.3.0"
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
if (response.data.success && Array.isArray(response.data.facilitators)) {
|
|
277
|
+
return response.data.facilitators.filter((f) => {
|
|
278
|
+
if (f.status !== "active") {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
if (f.network) {
|
|
282
|
+
return f.network === this.config.network;
|
|
283
|
+
}
|
|
284
|
+
if (f.chainId !== void 0) {
|
|
285
|
+
return f.chainId === this.chain.chainId;
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return [];
|
|
291
|
+
} catch (error) {
|
|
292
|
+
throw new Error(
|
|
293
|
+
`Failed to fetch facilitators for ${this.chain.displayName} (${this.config.network}): ${error.message || "Unknown error"}`
|
|
265
294
|
);
|
|
266
295
|
}
|
|
267
|
-
return [];
|
|
268
296
|
}
|
|
269
297
|
/**
|
|
270
|
-
* Select a random active facilitator
|
|
298
|
+
* Select a random active facilitator for the current network
|
|
271
299
|
*/
|
|
272
300
|
async selectRandomFacilitator() {
|
|
273
301
|
const facilitators = await this.getFacilitators();
|
|
274
302
|
if (facilitators.length === 0) {
|
|
275
|
-
throw new Error(
|
|
303
|
+
throw new Error(
|
|
304
|
+
`No active facilitators available for ${this.chain.displayName} (${this.config.network}, Chain ID: ${this.chain.chainId}). Please check that facilitators are registered for this network. API URL: ${this.config.apiUrl}`
|
|
305
|
+
);
|
|
276
306
|
}
|
|
277
307
|
const randomIndex = Math.floor(Math.random() * facilitators.length);
|
|
278
|
-
|
|
308
|
+
const selectedFacilitator = facilitators[randomIndex];
|
|
309
|
+
if (!selectedFacilitator.name) {
|
|
310
|
+
selectedFacilitator.name = `Facilitator ${selectedFacilitator.id.slice(0, 8)}`;
|
|
311
|
+
}
|
|
312
|
+
return selectedFacilitator;
|
|
279
313
|
}
|
|
280
314
|
/**
|
|
281
315
|
* Quick payment helper (static method)
|
package/dist/sdk.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/sdk/Facinet.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Facinet SDK - Main Class\n *\n * JavaScript/TypeScript SDK for integrating x402 payments\n * Supports multichain: Avalanche Fuji, Ethereum Sepolia, Base Sepolia, Polygon Amoy\n */\n\nimport axios from 'axios';\nimport { Wallet, JsonRpcProvider } from 'ethers';\nimport type { FacinetConfig, PaymentParams, PaymentResult, Facilitator, ChainConfig } from './types';\n\n// All 4 supported chains\nconst CHAINS: Record<string, ChainConfig> = {\n 'avalanche-fuji': {\n name: 'avalanche-fuji',\n displayName: 'Avalanche Fuji',\n chainId: 43113,\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n usdcAddress: '0x5425890298aed601595a70AB815c96711a31Bc65',\n usdcDecimals: 6,\n gasToken: 'AVAX',\n blockExplorer: 'https://testnet.snowtrace.io',\n erc3009DomainName: 'USD Coin',\n erc3009DomainVersion: '2',\n },\n 'ethereum-sepolia': {\n name: 'ethereum-sepolia',\n displayName: 'Ethereum Sepolia',\n chainId: 11155111,\n rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n usdcAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n usdcDecimals: 6,\n gasToken: 'ETH',\n blockExplorer: 'https://sepolia.etherscan.io',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n 'base-sepolia': {\n name: 'base-sepolia',\n displayName: 'Base Sepolia',\n chainId: 84532,\n rpcUrl: 'https://sepolia.base.org',\n usdcAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n usdcDecimals: 6,\n gasToken: 'ETH',\n blockExplorer: 'https://sepolia.basescan.org',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n 'polygon-amoy': {\n name: 'polygon-amoy',\n displayName: 'Polygon Amoy',\n chainId: 80002,\n rpcUrl: 'https://rpc-amoy.polygon.technology',\n usdcAddress: '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582',\n usdcDecimals: 6,\n gasToken: 'MATIC',\n blockExplorer: 'https://amoy.polygonscan.com',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n};\n\n// Legacy aliases for backwards compatibility\nconst NETWORK_ALIASES: Record<string, string> = {\n 'avalanche': 'avalanche-fuji',\n 'ethereum': 'ethereum-sepolia',\n 'polygon': 'polygon-amoy',\n 'base': 'base-sepolia',\n};\n\n/**\n * Resolve network name (handles legacy aliases)\n */\nfunction resolveNetwork(network: string): string {\n return NETWORK_ALIASES[network] || network;\n}\n\nexport class Facinet {\n private config: Required<Pick<FacinetConfig, 'apiUrl' | 'privateKey' | 'network' | 'rpcUrl'>>;\n private chain: ChainConfig;\n private wallet?: InstanceType<typeof Wallet>;\n\n constructor(config: FacinetConfig = {}) {\n const apiUrl = (config.apiUrl || 'https://x402-avalanche-chi.vercel.app').replace(/\\/$/, '');\n const resolvedNetwork = resolveNetwork(config.network || 'avalanche-fuji');\n\n this.config = {\n apiUrl,\n privateKey: config.privateKey || '',\n network: resolvedNetwork as any,\n rpcUrl: config.rpcUrl || '',\n };\n\n this.chain = CHAINS[resolvedNetwork];\n if (!this.chain) {\n throw new Error(\n `Unsupported network: ${config.network}. Supported networks: ${Object.keys(CHAINS).join(', ')}`\n );\n }\n\n if (this.config.privateKey) {\n const provider = new JsonRpcProvider(\n this.config.rpcUrl || this.chain.rpcUrl\n );\n this.wallet = new Wallet(this.config.privateKey, provider);\n }\n }\n\n /**\n * Get the current chain configuration\n */\n getChain(): ChainConfig {\n return { ...this.chain };\n }\n\n /**\n * Get all supported chains\n */\n static getSupportedChains(): ChainConfig[] {\n return Object.values(CHAINS);\n }\n\n /**\n * Get supported network names\n */\n static getSupportedNetworks(): string[] {\n return Object.keys(CHAINS);\n }\n\n /**\n * Make a payment via x402 facilitator network\n *\n * @example\n * ```typescript\n * const facinet = new Facinet({ network: 'base-sepolia' });\n * const result = await facinet.pay({\n * amount: '1',\n * recipient: '0xMerchantAddress',\n * payerAddress: '0xCustomerAddress'\n * });\n * console.log('Payment successful!', result.txHash);\n * ```\n */\n async pay(params: PaymentParams): Promise<PaymentResult> {\n if (!params.amount || parseFloat(params.amount) <= 0) {\n throw new Error('Invalid amount');\n }\n\n if (!params.recipient.match(/^0x[a-fA-F0-9]{40}$/)) {\n throw new Error('Invalid recipient address');\n }\n\n // Resolve payer address\n let payerAddress = params.payerAddress || '';\n if (!payerAddress) {\n if (this.wallet) {\n payerAddress = this.wallet.address as `0x${string}`;\n } else if (typeof window !== 'undefined' && (window as any).ethereum) {\n const accounts = await (window as any).ethereum.request({\n method: 'eth_requestAccounts',\n });\n payerAddress = accounts[0];\n } else {\n throw new Error(\n 'No payer address provided and no wallet available. Provide payerAddress or privateKey in config.'\n );\n }\n }\n\n payerAddress = payerAddress.toLowerCase() as `0x${string}`;\n const recipientAddress = params.recipient.toLowerCase();\n\n // Select random facilitator\n const facilitator = await this.selectRandomFacilitator();\n\n // Create ERC-3009 authorization\n const amount = BigInt(parseFloat(params.amount) * 1e6); // 6 decimals for USDC\n const validAfter = Math.floor(Date.now() / 1000) - 60;\n const validBefore = validAfter + 3600; // 1 hour validity\n const nonce =\n '0x' +\n Array.from({ length: 64 }, () =>\n Math.floor(Math.random() * 16).toString(16)\n ).join('');\n\n // EIP-712 Domain - uses chain-specific domain name\n const domain = {\n name: this.chain.erc3009DomainName,\n version: this.chain.erc3009DomainVersion,\n chainId: this.chain.chainId,\n verifyingContract: this.chain.usdcAddress,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n const value = {\n from: payerAddress,\n to: recipientAddress,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n };\n\n // Sign the authorization\n let signature: string;\n\n if (this.wallet) {\n signature = await this.wallet.signTypedData(domain, types, value);\n } else if (typeof window !== 'undefined' && (window as any).ethereum) {\n const { TypedDataEncoder } = await import('ethers');\n\n const messageForSigning = {\n from: payerAddress,\n to: recipientAddress,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n };\n\n const typedDataPayload = JSON.stringify({\n types: {\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n TransferWithAuthorization: types.TransferWithAuthorization,\n },\n domain,\n primaryType: 'TransferWithAuthorization',\n message: messageForSigning,\n });\n\n signature = await (window as any).ethereum.request({\n method: 'eth_signTypedData_v4',\n params: [payerAddress, typedDataPayload],\n });\n } else {\n throw new Error('No signing method available');\n }\n\n // Build payment payload\n const paymentPayload = {\n signature,\n authorization: {\n from: payerAddress,\n to: recipientAddress,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n },\n };\n\n // Submit to facilitator\n try {\n const response = await axios.post(\n `${this.config.apiUrl}/api/x402/settle-custom`,\n {\n facilitatorId: facilitator.id,\n paymentPayload,\n }\n );\n\n if (!response.data.success) {\n throw new Error(\n response.data.error || response.data.message || 'Payment failed'\n );\n }\n\n return {\n success: true,\n txHash: response.data.txHash,\n facilitator: {\n id: facilitator.id,\n name: facilitator.name,\n wallet: facilitator.facilitatorWallet,\n },\n payment: {\n from: payerAddress,\n to: recipientAddress,\n amount: params.amount,\n network: this.config.network,\n },\n };\n } catch (error: any) {\n if (error.response?.data) {\n const backendError =\n error.response.data.message || error.response.data.error;\n throw new Error(`Payment failed: ${backendError}`);\n }\n throw error;\n }\n }\n\n /**\n * Get all active facilitators\n */\n async getFacilitators(): Promise<Facilitator[]> {\n const response = await axios.get(\n `${this.config.apiUrl}/api/facilitator/list`\n );\n\n if (response.data.success) {\n return response.data.facilitators.filter(\n (f: Facilitator) => f.status === 'active'\n );\n }\n\n return [];\n }\n\n /**\n * Select a random active facilitator\n */\n async selectRandomFacilitator(): Promise<Facilitator> {\n const facilitators = await this.getFacilitators();\n\n if (facilitators.length === 0) {\n throw new Error('No active facilitators available');\n }\n\n const randomIndex = Math.floor(Math.random() * facilitators.length);\n return facilitators[randomIndex];\n }\n\n /**\n * Quick payment helper (static method)\n *\n * @example\n * ```typescript\n * // Pay on Base Sepolia\n * await Facinet.quickPay({\n * amount: '1',\n * recipient: '0xMerchantAddress',\n * privateKey: process.env.PRIVATE_KEY,\n * network: 'base-sepolia'\n * });\n * ```\n */\n static async quickPay(\n params: PaymentParams & { privateKey?: string; network?: FacinetConfig['network'] }\n ): Promise<PaymentResult> {\n const facinet = new Facinet({\n privateKey: params.privateKey,\n network: params.network,\n });\n\n return facinet.pay({\n amount: params.amount,\n recipient: params.recipient,\n payerAddress: params.payerAddress,\n });\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAOA,OAAO,WAAW;AAClB,SAAS,QAAQ,uBAAuB;AAIxC,IAAM,SAAsC;AAAA,EAC1C,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,oBAAoB;AAAA,IAClB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AACF;AAGA,IAAM,kBAA0C;AAAA,EAC9C,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AACV;
|
|
4
|
+
"sourcesContent": ["/**\n * Facinet SDK - Main Class\n *\n * JavaScript/TypeScript SDK for integrating x402 payments\n * Supports multichain: Avalanche Fuji, Ethereum Sepolia, Base Sepolia, Polygon Amoy\n */\n\nimport axios from 'axios';\nimport { Wallet, JsonRpcProvider } from 'ethers';\nimport type { FacinetConfig, PaymentParams, PaymentResult, Facilitator, ChainConfig } from './types';\n\n// All 4 supported chains\nconst CHAINS: Record<string, ChainConfig> = {\n 'avalanche-fuji': {\n name: 'avalanche-fuji',\n displayName: 'Avalanche Fuji',\n chainId: 43113,\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n usdcAddress: '0x5425890298aed601595a70AB815c96711a31Bc65',\n usdcDecimals: 6,\n gasToken: 'AVAX',\n blockExplorer: 'https://testnet.snowtrace.io',\n erc3009DomainName: 'USD Coin',\n erc3009DomainVersion: '2',\n },\n 'ethereum-sepolia': {\n name: 'ethereum-sepolia',\n displayName: 'Ethereum Sepolia',\n chainId: 11155111,\n rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n usdcAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n usdcDecimals: 6,\n gasToken: 'ETH',\n blockExplorer: 'https://sepolia.etherscan.io',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n 'base-sepolia': {\n name: 'base-sepolia',\n displayName: 'Base Sepolia',\n chainId: 84532,\n rpcUrl: 'https://sepolia.base.org',\n usdcAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n usdcDecimals: 6,\n gasToken: 'ETH',\n blockExplorer: 'https://sepolia.basescan.org',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n 'polygon-amoy': {\n name: 'polygon-amoy',\n displayName: 'Polygon Amoy',\n chainId: 80002,\n rpcUrl: 'https://rpc-amoy.polygon.technology',\n usdcAddress: '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582',\n usdcDecimals: 6,\n gasToken: 'MATIC',\n blockExplorer: 'https://amoy.polygonscan.com',\n erc3009DomainName: 'USDC',\n erc3009DomainVersion: '2',\n },\n};\n\n// Legacy aliases for backwards compatibility\nconst NETWORK_ALIASES: Record<string, string> = {\n 'avalanche': 'avalanche-fuji',\n 'ethereum': 'ethereum-sepolia',\n 'polygon': 'polygon-amoy',\n 'base': 'base-sepolia',\n};\n\n// Unified API URL for all networks\nconst DEFAULT_API_URL = 'https://facinet.vercel.app';\n\n/**\n * Resolve network name (handles legacy aliases)\n */\nfunction resolveNetwork(network: string): string {\n return NETWORK_ALIASES[network] || network;\n}\n\n/**\n * Get API URL for a network\n */\nfunction getApiUrlForNetwork(network: string, customApiUrl?: string): string {\n if (customApiUrl) {\n return customApiUrl.replace(/\\/$/, '');\n }\n return DEFAULT_API_URL;\n}\n\nexport class Facinet {\n private config: Required<Pick<FacinetConfig, 'apiUrl' | 'privateKey' | 'network' | 'rpcUrl'>>;\n private chain: ChainConfig;\n private wallet?: InstanceType<typeof Wallet>;\n\n constructor(config: FacinetConfig = {}) {\n const resolvedNetwork = resolveNetwork(config.network || 'avalanche-fuji');\n const apiUrl = getApiUrlForNetwork(resolvedNetwork, config.apiUrl);\n\n this.config = {\n apiUrl,\n privateKey: config.privateKey || '',\n network: resolvedNetwork as any,\n rpcUrl: config.rpcUrl || '',\n };\n\n this.chain = CHAINS[resolvedNetwork];\n if (!this.chain) {\n throw new Error(\n `Unsupported network: ${config.network}. Supported networks: ${Object.keys(CHAINS).join(', ')}`\n );\n }\n\n if (this.config.privateKey) {\n const provider = new JsonRpcProvider(\n this.config.rpcUrl || this.chain.rpcUrl\n );\n this.wallet = new Wallet(this.config.privateKey, provider);\n }\n }\n\n /**\n * Get the current chain configuration\n */\n getChain(): ChainConfig {\n return { ...this.chain };\n }\n\n /**\n * Get all supported chains\n */\n static getSupportedChains(): ChainConfig[] {\n return Object.values(CHAINS);\n }\n\n /**\n * Get supported network names\n */\n static getSupportedNetworks(): string[] {\n return Object.keys(CHAINS);\n }\n\n /**\n * Make a payment via x402 facilitator network\n *\n * @example\n * ```typescript\n * const facinet = new Facinet({ network: 'base-sepolia' });\n * const result = await facinet.pay({\n * amount: '1',\n * recipient: '0xMerchantAddress',\n * payerAddress: '0xCustomerAddress'\n * });\n * console.log('Payment successful!', result.txHash);\n * ```\n */\n async pay(params: PaymentParams): Promise<PaymentResult> {\n if (!params.amount || parseFloat(params.amount) <= 0) {\n throw new Error('Invalid amount');\n }\n\n if (!params.recipient.match(/^0x[a-fA-F0-9]{40}$/)) {\n throw new Error('Invalid recipient address');\n }\n\n // Resolve payer address\n let payerAddress = params.payerAddress || '';\n if (!payerAddress) {\n if (this.wallet) {\n payerAddress = this.wallet.address as `0x${string}`;\n } else if (typeof window !== 'undefined' && (window as any).ethereum) {\n const accounts = await (window as any).ethereum.request({\n method: 'eth_requestAccounts',\n });\n payerAddress = accounts[0];\n } else {\n throw new Error(\n 'No payer address provided and no wallet available. Provide payerAddress or privateKey in config.'\n );\n }\n }\n\n payerAddress = payerAddress.toLowerCase() as `0x${string}`;\n const recipientAddress = params.recipient.toLowerCase();\n\n // Select random facilitator\n const facilitator = await this.selectRandomFacilitator();\n\n // Create ERC-3009 authorization\n const amount = BigInt(parseFloat(params.amount) * 1e6); // 6 decimals for USDC\n const validAfter = Math.floor(Date.now() / 1000) - 60;\n const validBefore = validAfter + 3600; // 1 hour validity\n const nonce =\n '0x' +\n Array.from({ length: 64 }, () =>\n Math.floor(Math.random() * 16).toString(16)\n ).join('');\n\n // EIP-712 Domain - uses chain-specific domain name\n const domain = {\n name: this.chain.erc3009DomainName,\n version: this.chain.erc3009DomainVersion,\n chainId: this.chain.chainId,\n verifyingContract: this.chain.usdcAddress,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n const value = {\n from: payerAddress,\n to: recipientAddress,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n };\n\n // Sign the authorization\n let signature: string;\n\n if (this.wallet) {\n signature = await this.wallet.signTypedData(domain, types, value);\n } else if (typeof window !== 'undefined' && (window as any).ethereum) {\n const { TypedDataEncoder } = await import('ethers');\n\n const messageForSigning = {\n from: payerAddress,\n to: recipientAddress,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n };\n\n const typedDataPayload = JSON.stringify({\n types: {\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n TransferWithAuthorization: types.TransferWithAuthorization,\n },\n domain,\n primaryType: 'TransferWithAuthorization',\n message: messageForSigning,\n });\n\n signature = await (window as any).ethereum.request({\n method: 'eth_signTypedData_v4',\n params: [payerAddress, typedDataPayload],\n });\n } else {\n throw new Error('No signing method available');\n }\n\n // Build payment payload\n const paymentPayload = {\n signature,\n authorization: {\n from: payerAddress,\n to: recipientAddress,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n },\n };\n\n // Submit to facilitator\n try {\n const response = await axios.post(\n `${this.config.apiUrl}/api/x402/settle-custom`,\n {\n facilitatorId: facilitator.id,\n paymentPayload,\n }\n );\n\n if (!response.data.success) {\n throw new Error(\n response.data.error || response.data.message || 'Payment failed'\n );\n }\n\n return {\n success: true,\n txHash: response.data.txHash,\n facilitator: {\n id: facilitator.id,\n name: facilitator.name || `Facilitator ${facilitator.id.slice(0, 8)}`,\n wallet: facilitator.facilitatorWallet,\n },\n payment: {\n from: payerAddress,\n to: recipientAddress,\n amount: params.amount,\n network: this.config.network,\n },\n };\n } catch (error: any) {\n if (error.response?.data) {\n const backendError =\n error.response.data.message || error.response.data.error;\n throw new Error(`Payment failed: ${backendError}`);\n }\n throw error;\n }\n }\n\n /**\n * Get all active facilitators for the current network\n */\n async getFacilitators(): Promise<Facilitator[]> {\n try {\n const response = await axios.get(\n `${this.config.apiUrl}/api/facilitator/list`,\n {\n timeout: 10000,\n headers: {\n 'User-Agent': 'Facinet-SDK/2.3.0',\n },\n }\n );\n\n if (response.data.success && Array.isArray(response.data.facilitators)) {\n // Filter by status and network/chainId\n return response.data.facilitators.filter((f: Facilitator) => {\n // Must be active\n if (f.status !== 'active') {\n return false;\n }\n \n // If facilitator has network or chainId, match it with current chain\n if (f.network) {\n return f.network === this.config.network;\n }\n \n if (f.chainId !== undefined) {\n return f.chainId === this.chain.chainId;\n }\n \n // If no network/chainId specified, include it (backwards compatibility)\n return true;\n });\n }\n\n return [];\n } catch (error: any) {\n throw new Error(\n `Failed to fetch facilitators for ${this.chain.displayName} (${this.config.network}): ${error.message || 'Unknown error'}`\n );\n }\n }\n\n /**\n * Select a random active facilitator for the current network\n */\n async selectRandomFacilitator(): Promise<Facilitator> {\n const facilitators = await this.getFacilitators();\n\n if (facilitators.length === 0) {\n throw new Error(\n `No active facilitators available for ${this.chain.displayName} (${this.config.network}, Chain ID: ${this.chain.chainId}). ` +\n `Please check that facilitators are registered for this network. API URL: ${this.config.apiUrl}`\n );\n }\n\n const randomIndex = Math.floor(Math.random() * facilitators.length);\n const selectedFacilitator = facilitators[randomIndex];\n \n // Ensure facilitator has a name\n if (!selectedFacilitator.name) {\n selectedFacilitator.name = `Facilitator ${selectedFacilitator.id.slice(0, 8)}`;\n }\n \n return selectedFacilitator;\n }\n\n /**\n * Quick payment helper (static method)\n *\n * @example\n * ```typescript\n * // Pay on Base Sepolia\n * await Facinet.quickPay({\n * amount: '1',\n * recipient: '0xMerchantAddress',\n * privateKey: process.env.PRIVATE_KEY,\n * network: 'base-sepolia'\n * });\n * ```\n */\n static async quickPay(\n params: PaymentParams & { privateKey?: string; network?: FacinetConfig['network'] }\n ): Promise<PaymentResult> {\n const facinet = new Facinet({\n privateKey: params.privateKey,\n network: params.network,\n });\n\n return facinet.pay({\n amount: params.amount,\n recipient: params.recipient,\n payerAddress: params.payerAddress,\n });\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAOA,OAAO,WAAW;AAClB,SAAS,QAAQ,uBAAuB;AAIxC,IAAM,SAAsC;AAAA,EAC1C,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,oBAAoB;AAAA,IAClB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AACF;AAGA,IAAM,kBAA0C;AAAA,EAC9C,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AACV;AAGA,IAAM,kBAAkB;AAKxB,SAAS,eAAe,SAAyB;AAC/C,SAAO,gBAAgB,OAAO,KAAK;AACrC;AAKA,SAAS,oBAAoB,SAAiB,cAA+B;AAC3E,MAAI,cAAc;AAChB,WAAO,aAAa,QAAQ,OAAO,EAAE;AAAA,EACvC;AACA,SAAO;AACT;AAEO,IAAM,UAAN,MAAM,SAAQ;AAAA,EAKnB,YAAY,SAAwB,CAAC,GAAG;AACtC,UAAM,kBAAkB,eAAe,OAAO,WAAW,gBAAgB;AACzE,UAAM,SAAS,oBAAoB,iBAAiB,OAAO,MAAM;AAEjE,SAAK,SAAS;AAAA,MACZ;AAAA,MACA,YAAY,OAAO,cAAc;AAAA,MACjC,SAAS;AAAA,MACT,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAEA,SAAK,QAAQ,OAAO,eAAe;AACnC,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI;AAAA,QACR,wBAAwB,OAAO,OAAO,yBAAyB,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,MAC/F;AAAA,IACF;AAEA,QAAI,KAAK,OAAO,YAAY;AAC1B,YAAM,WAAW,IAAI;AAAA,QACnB,KAAK,OAAO,UAAU,KAAK,MAAM;AAAA,MACnC;AACA,WAAK,SAAS,IAAI,OAAO,KAAK,OAAO,YAAY,QAAQ;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAwB;AACtB,WAAO,EAAE,GAAG,KAAK,MAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBAAoC;AACzC,WAAO,OAAO,OAAO,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,uBAAiC;AACtC,WAAO,OAAO,KAAK,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,IAAI,QAA+C;AACvD,QAAI,CAAC,OAAO,UAAU,WAAW,OAAO,MAAM,KAAK,GAAG;AACpD,YAAM,IAAI,MAAM,gBAAgB;AAAA,IAClC;AAEA,QAAI,CAAC,OAAO,UAAU,MAAM,qBAAqB,GAAG;AAClD,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAGA,QAAI,eAAe,OAAO,gBAAgB;AAC1C,QAAI,CAAC,cAAc;AACjB,UAAI,KAAK,QAAQ;AACf,uBAAe,KAAK,OAAO;AAAA,MAC7B,WAAW,OAAO,WAAW,eAAgB,OAAe,UAAU;AACpE,cAAM,WAAW,MAAO,OAAe,SAAS,QAAQ;AAAA,UACtD,QAAQ;AAAA,QACV,CAAC;AACD,uBAAe,SAAS,CAAC;AAAA,MAC3B,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,mBAAe,aAAa,YAAY;AACxC,UAAM,mBAAmB,OAAO,UAAU,YAAY;AAGtD,UAAM,cAAc,MAAM,KAAK,wBAAwB;AAGvD,UAAM,SAAS,OAAO,WAAW,OAAO,MAAM,IAAI,GAAG;AACrD,UAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AACnD,UAAM,cAAc,aAAa;AACjC,UAAM,QACJ,OACA,MAAM;AAAA,MAAK,EAAE,QAAQ,GAAG;AAAA,MAAG,MACzB,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,EAAE,SAAS,EAAE;AAAA,IAC5C,EAAE,KAAK,EAAE;AAGX,UAAM,SAAS;AAAA,MACb,MAAM,KAAK,MAAM;AAAA,MACjB,SAAS,KAAK,MAAM;AAAA,MACpB,SAAS,KAAK,MAAM;AAAA,MACpB,mBAAmB,KAAK,MAAM;AAAA,IAChC;AAEA,UAAM,QAAQ;AAAA,MACZ,2BAA2B;AAAA,QACzB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,QAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,QAC9B,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,QACjC,EAAE,MAAM,cAAc,MAAM,UAAU;AAAA,QACtC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,QACvC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,QAAI;AAEJ,QAAI,KAAK,QAAQ;AACf,kBAAY,MAAM,KAAK,OAAO,cAAc,QAAQ,OAAO,KAAK;AAAA,IAClE,WAAW,OAAO,WAAW,eAAgB,OAAe,UAAU;AACpE,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,QAAQ;AAElD,YAAM,oBAAoB;AAAA,QACxB,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,OAAO,OAAO,SAAS;AAAA,QACvB,YAAY,WAAW,SAAS;AAAA,QAChC,aAAa,YAAY,SAAS;AAAA,QAClC;AAAA,MACF;AAEA,YAAM,mBAAmB,KAAK,UAAU;AAAA,QACtC,OAAO;AAAA,UACL,cAAc;AAAA,YACZ,EAAE,MAAM,QAAQ,MAAM,SAAS;AAAA,YAC/B,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,YAClC,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,YACnC,EAAE,MAAM,qBAAqB,MAAM,UAAU;AAAA,UAC/C;AAAA,UACA,2BAA2B,MAAM;AAAA,QACnC;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAED,kBAAY,MAAO,OAAe,SAAS,QAAQ;AAAA,QACjD,QAAQ;AAAA,QACR,QAAQ,CAAC,cAAc,gBAAgB;AAAA,MACzC,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAGA,UAAM,iBAAiB;AAAA,MACrB;AAAA,MACA,eAAe;AAAA,QACb,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,OAAO,OAAO,SAAS;AAAA,QACvB,YAAY,WAAW,SAAS;AAAA,QAChC,aAAa,YAAY,SAAS;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM;AAAA,QAC3B,GAAG,KAAK,OAAO,MAAM;AAAA,QACrB;AAAA,UACE,eAAe,YAAY;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,KAAK,SAAS;AAC1B,cAAM,IAAI;AAAA,UACR,SAAS,KAAK,SAAS,SAAS,KAAK,WAAW;AAAA,QAClD;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,SAAS,KAAK;AAAA,QACtB,aAAa;AAAA,UACX,IAAI,YAAY;AAAA,UAChB,MAAM,YAAY,QAAQ,eAAe,YAAY,GAAG,MAAM,GAAG,CAAC,CAAC;AAAA,UACnE,QAAQ,YAAY;AAAA,QACtB;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,QAAQ,OAAO;AAAA,UACf,SAAS,KAAK,OAAO;AAAA,QACvB;AAAA,MACF;AAAA,IACF,SAAS,OAAY;AACnB,UAAI,MAAM,UAAU,MAAM;AACxB,cAAM,eACJ,MAAM,SAAS,KAAK,WAAW,MAAM,SAAS,KAAK;AACrD,cAAM,IAAI,MAAM,mBAAmB,YAAY,EAAE;AAAA,MACnD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAA0C;AAC9C,QAAI;AACF,YAAM,WAAW,MAAM,MAAM;AAAA,QAC3B,GAAG,KAAK,OAAO,MAAM;AAAA,QACrB;AAAA,UACE,SAAS;AAAA,UACT,SAAS;AAAA,YACP,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,KAAK,WAAW,MAAM,QAAQ,SAAS,KAAK,YAAY,GAAG;AAEtE,eAAO,SAAS,KAAK,aAAa,OAAO,CAAC,MAAmB;AAE3D,cAAI,EAAE,WAAW,UAAU;AACzB,mBAAO;AAAA,UACT;AAGA,cAAI,EAAE,SAAS;AACb,mBAAO,EAAE,YAAY,KAAK,OAAO;AAAA,UACnC;AAEA,cAAI,EAAE,YAAY,QAAW;AAC3B,mBAAO,EAAE,YAAY,KAAK,MAAM;AAAA,UAClC;AAGA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,aAAO,CAAC;AAAA,IACV,SAAS,OAAY;AACnB,YAAM,IAAI;AAAA,QACR,oCAAoC,KAAK,MAAM,WAAW,KAAK,KAAK,OAAO,OAAO,MAAM,MAAM,WAAW,eAAe;AAAA,MAC1H;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAAgD;AACpD,UAAM,eAAe,MAAM,KAAK,gBAAgB;AAEhD,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR,wCAAwC,KAAK,MAAM,WAAW,KAAK,KAAK,OAAO,OAAO,eAAe,KAAK,MAAM,OAAO,+EAC3C,KAAK,OAAO,MAAM;AAAA,MAChG;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,MAAM,KAAK,OAAO,IAAI,aAAa,MAAM;AAClE,UAAM,sBAAsB,aAAa,WAAW;AAGpD,QAAI,CAAC,oBAAoB,MAAM;AAC7B,0BAAoB,OAAO,eAAe,oBAAoB,GAAG,MAAM,GAAG,CAAC,CAAC;AAAA,IAC9E;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,aAAa,SACX,QACwB;AACxB,UAAM,UAAU,IAAI,SAAQ;AAAA,MAC1B,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,WAAO,QAAQ,IAAI;AAAA,MACjB,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,IACvB,CAAC;AAAA,EACH;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
7
|
* Get all active facilitators
|
|
8
|
+
* @param apiUrl - API URL for the facilitator network
|
|
9
|
+
* @param chainId - Optional chain ID to filter facilitators by network
|
|
8
10
|
*/
|
|
9
|
-
export declare function listFacilitators(apiUrl: string): Promise<any>;
|
|
11
|
+
export declare function listFacilitators(apiUrl: string, chainId?: number): Promise<any>;
|
|
10
12
|
/**
|
|
11
13
|
* Select a random active facilitator
|
|
14
|
+
* @param apiUrl - API URL for the facilitator network
|
|
15
|
+
* @param chainId - Optional chain ID to filter facilitators by network
|
|
12
16
|
*/
|
|
13
|
-
export declare function selectRandomFacilitator(apiUrl: string): Promise<any>;
|
|
17
|
+
export declare function selectRandomFacilitator(apiUrl: string, chainId?: number): Promise<any>;
|
|
14
18
|
/**
|
|
15
19
|
* Get facilitator by ID
|
|
16
20
|
*/
|
package/dist/utils/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,gBA+BtE;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,gBAmB7E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAclE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAEpE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;;;;GAkBrE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,iBASnE;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,GAAG;;;;GAmBpB"}
|
package/dist/utils/api.js
CHANGED
|
@@ -18,8 +18,10 @@ exports.submitPayment = submitPayment;
|
|
|
18
18
|
const axios_1 = __importDefault(require("axios"));
|
|
19
19
|
/**
|
|
20
20
|
* Get all active facilitators
|
|
21
|
+
* @param apiUrl - API URL for the facilitator network
|
|
22
|
+
* @param chainId - Optional chain ID to filter facilitators by network
|
|
21
23
|
*/
|
|
22
|
-
async function listFacilitators(apiUrl) {
|
|
24
|
+
async function listFacilitators(apiUrl, chainId) {
|
|
23
25
|
try {
|
|
24
26
|
const response = await axios_1.default.get(`${apiUrl}/api/facilitator/list`, {
|
|
25
27
|
timeout: 10000,
|
|
@@ -27,25 +29,44 @@ async function listFacilitators(apiUrl) {
|
|
|
27
29
|
'User-Agent': 'Facinet-CLI/2.3.0',
|
|
28
30
|
},
|
|
29
31
|
});
|
|
30
|
-
if (response.data.success) {
|
|
31
|
-
return response.data.facilitators.filter((f) =>
|
|
32
|
+
if (response.data.success && Array.isArray(response.data.facilitators)) {
|
|
33
|
+
return response.data.facilitators.filter((f) => {
|
|
34
|
+
// Must be active
|
|
35
|
+
if (f.status !== 'active') {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// If chainId is provided, filter by it
|
|
39
|
+
if (chainId !== undefined && f.chainId !== undefined) {
|
|
40
|
+
return f.chainId === chainId;
|
|
41
|
+
}
|
|
42
|
+
// If facilitator has network property, it should match (handled by SDK)
|
|
43
|
+
return true;
|
|
44
|
+
});
|
|
32
45
|
}
|
|
33
46
|
return [];
|
|
34
47
|
}
|
|
35
48
|
catch (error) {
|
|
36
|
-
throw new Error(`Failed to fetch facilitators: ${error.message || error.code || 'Unknown error'}`);
|
|
49
|
+
throw new Error(`Failed to fetch facilitators from ${apiUrl}: ${error.message || error.code || 'Unknown error'}`);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
52
|
/**
|
|
40
53
|
* Select a random active facilitator
|
|
54
|
+
* @param apiUrl - API URL for the facilitator network
|
|
55
|
+
* @param chainId - Optional chain ID to filter facilitators by network
|
|
41
56
|
*/
|
|
42
|
-
async function selectRandomFacilitator(apiUrl) {
|
|
43
|
-
const facilitators = await listFacilitators(apiUrl);
|
|
57
|
+
async function selectRandomFacilitator(apiUrl, chainId) {
|
|
58
|
+
const facilitators = await listFacilitators(apiUrl, chainId);
|
|
44
59
|
if (facilitators.length === 0) {
|
|
45
|
-
|
|
60
|
+
const networkInfo = chainId ? ` (Chain ID: ${chainId})` : '';
|
|
61
|
+
throw new Error(`No active facilitators available${networkInfo}. API URL: ${apiUrl}`);
|
|
46
62
|
}
|
|
47
63
|
const randomIndex = Math.floor(Math.random() * facilitators.length);
|
|
48
|
-
|
|
64
|
+
const facilitator = facilitators[randomIndex];
|
|
65
|
+
// Ensure facilitator has a name
|
|
66
|
+
if (!facilitator.name) {
|
|
67
|
+
facilitator.name = `Facilitator ${facilitator.id?.slice(0, 8) || 'Unknown'}`;
|
|
68
|
+
}
|
|
69
|
+
return facilitator;
|
|
49
70
|
}
|
|
50
71
|
/**
|
|
51
72
|
* Get facilitator by ID
|
package/dist/utils/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED