@ghostspeak/sdk 2.0.5 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +152 -30
  2. package/dist/GhostSpeakClient-CWmGaM9Q.d.ts +1007 -0
  3. package/dist/StakingModule-C5rzuOWb.d.ts +2526 -0
  4. package/dist/{agent-M74TCRON.js → agent-5YLZ7DAC.js} +4 -4
  5. package/dist/{agent-M74TCRON.js.map → agent-5YLZ7DAC.js.map} +1 -1
  6. package/dist/batch-operations-45CQFEID.js +4 -0
  7. package/dist/batch-operations-45CQFEID.js.map +1 -0
  8. package/dist/browser.d.ts +45 -554
  9. package/dist/browser.js +15 -842
  10. package/dist/browser.js.map +1 -1
  11. package/dist/chunk-AL3HQN73.js +754 -0
  12. package/dist/chunk-AL3HQN73.js.map +1 -0
  13. package/dist/chunk-BF3IQ35I.js +284 -0
  14. package/dist/chunk-BF3IQ35I.js.map +1 -0
  15. package/dist/chunk-BQDGRTVP.js +168 -0
  16. package/dist/chunk-BQDGRTVP.js.map +1 -0
  17. package/dist/chunk-C5CDA3WX.js +7314 -0
  18. package/dist/chunk-C5CDA3WX.js.map +1 -0
  19. package/dist/chunk-E3FD2CNY.js +1869 -0
  20. package/dist/chunk-E3FD2CNY.js.map +1 -0
  21. package/dist/{chunk-V3SOFUAZ.js → chunk-G7S6B6WB.js} +327 -493
  22. package/dist/chunk-G7S6B6WB.js.map +1 -0
  23. package/dist/chunk-IHVDQ4YI.js +4231 -0
  24. package/dist/chunk-IHVDQ4YI.js.map +1 -0
  25. package/dist/chunk-JV2SWONF.js +98 -0
  26. package/dist/chunk-JV2SWONF.js.map +1 -0
  27. package/dist/chunk-KB6CKIUK.js +231 -0
  28. package/dist/chunk-KB6CKIUK.js.map +1 -0
  29. package/dist/chunk-RIZZPLLB.js +343 -0
  30. package/dist/chunk-RIZZPLLB.js.map +1 -0
  31. package/dist/chunk-S74EH3KD.js +7890 -0
  32. package/dist/chunk-S74EH3KD.js.map +1 -0
  33. package/dist/chunk-SFTSZ3LC.js +156 -0
  34. package/dist/chunk-SFTSZ3LC.js.map +1 -0
  35. package/dist/chunk-SKMJJ3Q6.js +125 -0
  36. package/dist/chunk-SKMJJ3Q6.js.map +1 -0
  37. package/dist/chunk-SZGFSCNU.js +3682 -0
  38. package/dist/chunk-SZGFSCNU.js.map +1 -0
  39. package/dist/chunk-TTB4OS2D.js +69 -0
  40. package/dist/chunk-TTB4OS2D.js.map +1 -0
  41. package/dist/chunk-UP2VWCW5.js +33 -0
  42. package/dist/{chunk-NSBPE2FW.js.map → chunk-UP2VWCW5.js.map} +1 -1
  43. package/dist/{chunk-UJUGGLMT.js → chunk-VQZQCHUT.js} +5 -5
  44. package/dist/{chunk-UJUGGLMT.js.map → chunk-VQZQCHUT.js.map} +1 -1
  45. package/dist/client.d.ts +6 -4
  46. package/dist/client.js +12 -10
  47. package/dist/createAgentAuthorization-ULG47ZJI.js +5 -0
  48. package/dist/createAgentAuthorization-ULG47ZJI.js.map +1 -0
  49. package/dist/credentials.d.ts +155 -0
  50. package/dist/credentials.js +4 -0
  51. package/dist/credentials.js.map +1 -0
  52. package/dist/crypto.js +2 -2
  53. package/dist/errors.js +1 -1
  54. package/dist/feature-flags-B1g0DCPe.d.ts +1181 -0
  55. package/dist/generated-EG5USUFG.js +9 -0
  56. package/dist/{generated-VNLHMR6Y.js.map → generated-EG5USUFG.js.map} +1 -1
  57. package/dist/{ghostspeak_wasm-SB2RPJ3D.js → ghostspeak_wasm-F227HOSM.js} +3 -3
  58. package/dist/{ghostspeak_wasm-SB2RPJ3D.js.map → ghostspeak_wasm-F227HOSM.js.map} +1 -1
  59. package/dist/index.d.ts +1210 -1506
  60. package/dist/index.js +601 -3532
  61. package/dist/index.js.map +1 -1
  62. package/dist/metafile-esm.json +1 -1
  63. package/dist/minimal/core-minimal.d.ts +2383 -1264
  64. package/dist/minimal/core-minimal.js +9 -9
  65. package/dist/minimal/core-minimal.js.map +1 -1
  66. package/dist/nacl-fast-W5BJ3KZ2.js +2229 -0
  67. package/dist/nacl-fast-W5BJ3KZ2.js.map +1 -0
  68. package/dist/pda-4KP7CURF.js +4 -0
  69. package/dist/pda-4KP7CURF.js.map +1 -0
  70. package/dist/pda-Ce7VYg4T.d.ts +25 -0
  71. package/dist/reputation-types-Yebf0Rm_.d.ts +1071 -0
  72. package/dist/revokeAuthorization-OK7E7OK3.js +5 -0
  73. package/dist/revokeAuthorization-OK7E7OK3.js.map +1 -0
  74. package/dist/signature-verification-DGxR4aYQ.d.ts +448 -0
  75. package/dist/types.js +1 -1
  76. package/dist/updateReputationWithAuth-Y4ONEVSP.js +5 -0
  77. package/dist/updateReputationWithAuth-Y4ONEVSP.js.map +1 -0
  78. package/dist/utils.d.ts +69 -203
  79. package/dist/utils.js +15 -153
  80. package/dist/utils.js.map +1 -1
  81. package/package.json +28 -31
  82. package/dist/.tsbuildinfo +0 -1
  83. package/dist/GhostSpeakClient-hsGuGg__.d.ts +0 -860
  84. package/dist/GovernanceModule-DQYYys-H.d.ts +0 -1766
  85. package/dist/chunk-ASQXX4IT.js +0 -572
  86. package/dist/chunk-ASQXX4IT.js.map +0 -1
  87. package/dist/chunk-COGZFWOT.js +0 -19657
  88. package/dist/chunk-COGZFWOT.js.map +0 -1
  89. package/dist/chunk-FKRN4PW5.js +0 -1667
  90. package/dist/chunk-FKRN4PW5.js.map +0 -1
  91. package/dist/chunk-GMHIUK2R.js +0 -7526
  92. package/dist/chunk-GMHIUK2R.js.map +0 -1
  93. package/dist/chunk-IAWBZYPE.js +0 -356
  94. package/dist/chunk-IAWBZYPE.js.map +0 -1
  95. package/dist/chunk-NSBPE2FW.js +0 -15
  96. package/dist/chunk-OWYHJG6H.js +0 -13311
  97. package/dist/chunk-OWYHJG6H.js.map +0 -1
  98. package/dist/chunk-RDDPOFR5.js +0 -3
  99. package/dist/chunk-RDDPOFR5.js.map +0 -1
  100. package/dist/chunk-RERCHKZP.js +0 -35
  101. package/dist/chunk-RERCHKZP.js.map +0 -1
  102. package/dist/chunk-TVVGXYCI.js +0 -2887
  103. package/dist/chunk-TVVGXYCI.js.map +0 -1
  104. package/dist/chunk-V3SOFUAZ.js.map +0 -1
  105. package/dist/chunk-ZGP5552B.js +0 -377
  106. package/dist/chunk-ZGP5552B.js.map +0 -1
  107. package/dist/chunk-ZWOYNHVK.js +0 -196
  108. package/dist/chunk-ZWOYNHVK.js.map +0 -1
  109. package/dist/dist/.tsbuildinfo +0 -1
  110. package/dist/elgamal-VZLWB3XK.js +0 -5
  111. package/dist/elgamal-VZLWB3XK.js.map +0 -1
  112. package/dist/feature-flags-V722ZuXO.d.ts +0 -3512
  113. package/dist/generated-VNLHMR6Y.js +0 -5
  114. package/dist/ipfs-types-BOt9ZNg4.d.ts +0 -592
  115. package/dist/multisigConfig-BzEhy6jy.d.ts +0 -58
  116. package/dist/pda-B_nS8SbD.d.ts +0 -114
  117. package/dist/pda-S4BFJVGE.js +0 -4
  118. package/dist/pda-S4BFJVGE.js.map +0 -1
  119. package/dist/system-addresses-BFNLEbFx.d.ts +0 -857
  120. package/dist/token-2022-rpc-RALH4RK7.js +0 -593
  121. package/dist/token-2022-rpc-RALH4RK7.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,31 +1,29 @@
1
- export { WorkOrderModule } from './chunk-ZWOYNHVK.js';
2
- export { CredentialKind, CredentialModule, CredentialStatus, CrossmintVCClient, GHOSTSPEAK_CREDENTIAL_TYPES, GhostSpeakClient, MultisigModule, UnifiedCredentialService, GhostSpeakClient_default as default, lamportsToSol, sol } from './chunk-FKRN4PW5.js';
3
- export { AgentModule, BaseModule, ChannelModule, DEFAULT_IPFS_CONFIG, EscrowModule, GHOSTSPEAK_PROGRAM_ID, GovernanceModule, IPFSUtils, InstructionBuilder, MarketplaceModule, RpcClient, Token2022Module, createIPFSUtils, createMetadataUri, determineStorageMethod } from './chunk-TVVGXYCI.js';
1
+ export { batchGetAccounts, batchGetAccountsWithRetry, batchGetAndMap, batchGetExistingAccounts, createBatchFetcher } from './chunk-SKMJJ3Q6.js';
2
+ export { BaseReputationAdapter, GHOSTSPEAK_PROGRAM_ID, ReputationSource } from './chunk-TTB4OS2D.js';
3
+ export { AuthorizationModule, DidModule, GhostSpeakClient, PrivacyModule, UnifiedCredentialService, calculateVisibleScore, canViewerAccess, GhostSpeakClient_default as default, filterMetricsByVisibility, getDefaultMetricVisibility, getRangeDisplayString, getReputationTier, getScoreRange, getTierDisplayName, lamportsToSol, sol, validatePrivacySettings } from './chunk-E3FD2CNY.js';
4
+ import { init_MultiSourceAggregator } from './chunk-SZGFSCNU.js';
5
+ export { AgentModule, BaseModule, CacheManager, CredentialKind, CredentialModule, CredentialStatus, DEFAULT_IPFS_CONFIG, DidError, DidErrorClass, GovernanceModule, IPFSUtils, InstructionBuilder, MultiSourceAggregator, MultisigModule, PayAIClient, ReputationModule, RpcClient, ServiceEndpointType, VerificationMethodType, VerificationRelationship, canPerformAction, createEd25519VerificationMethod, createIPFSUtils, createMetadataUri, createPayAIClient, createServiceEndpoint, deriveDidDocumentPda, determineStorageMethod, didDocumentToJson, exportAsW3CDidDocument, extractPaymentRequirements, generateDidString, getIdentifierFromDid, getMethodsForRelationship, getNetworkFromDid, isDidActive, isPaymentRequired, parseDidString, payAIFetch, validateDidString } from './chunk-SZGFSCNU.js';
4
6
  export { AccountNotFoundError, ErrorFactory, ErrorHandler, GhostSpeakError, InsufficientBalanceError, InvalidInputError, NetworkError, SimulationFailedError, TimeoutError, TransactionFailedError, ValidationError } from './chunk-5DMB3UAV.js';
5
- export { decrypt, elgamal_exports as elgamal, encrypt, generateKeypair, generateTransferProof, generateWithdrawProof, isWasmAvailable, loadWasmModule, wasm_bridge_exports as wasmBridge } from './chunk-UJUGGLMT.js';
6
- import { getFeatureFlags, ClientEncryptionService } from './chunk-V3SOFUAZ.js';
7
- export { ClientEncryptionService, FeatureFlagManager, TokenAccountState, TokenExtension, TokenProgram, basisPointsToPercentage, calculateCompoundInterest, calculateInterest, calculateRequiredAmountForNetTransfer, calculateTransferFee, canTransfer, createDiscriminatorErrorMessage, createMigrationPlan, createMigrationReport, createTransferHookInstruction, deriveAssociatedTokenAddress, deriveSplTokenAssociatedTokenAddress, deriveToken2022AssociatedTokenAddress, deserializeTokenMetadata, detectTokenProgram, diagnoseAccountFromChain, diagnoseBatchFromChain, estimateAccumulatedFees, estimateComputeUnits, exportDiagnosticReport, extractLegacyData, formatBasisPoints, formatTokenAmount, generateConfidentialTransferProof, generateLocalPrivacyProof, getAllAssociatedTokenAddresses, getAssociatedTokenAccount, getConfidentialTransferConfig, getFeatureFlags, getInterestBearingConfig, getMigrationInstructions, getRequiredExtensions, getTokenProgramAddress, getTokenProgramFromAddress, getTokenProgramType, getTransferFeeConfig, hasConfidentialTransferExtension, hasInterestBearingExtension, hasTransferFeeExtension, inspectAccountData, isFeatureEnabled, isToken2022Mint, parseTokenAmount, percentageToBasisPoints, runAccountDiagnostics, runBatchDiagnostics, safeDecodeAgent, serializeTokenMetadata, simulateMigration, validateAccountDiscriminator, validateAssociatedTokenAddress, validateTransferHookInstruction, verifyConfidentialTransferProof, verifyLocalPrivacyProof } from './chunk-V3SOFUAZ.js';
8
- import './chunk-IAWBZYPE.js';
9
- export { deriveMultisigPda, deriveProposalPda } from './chunk-ZGP5552B.js';
10
- export { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, GhostSpeakSDKError, INSTRUCTION_MAPPINGS, IPFSClient, InstructionValidationError, NATIVE_MINT_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, createAccountMismatchError, createErrorContext, debugInstructionCall, enhanceErrorMessage, enhanceTransactionError, extractInstructionName, generateAccountValidationError, getAccountRequirements, getInstructionMapping, getPDAAccounts, getRequiredSigners, getWritableAccounts, isKnownInstruction, logEnhancedError, validateInstructionAccounts, validatePreconditions, withEnhancedErrors, withEnhancedErrorsSync } from './chunk-OWYHJG6H.js';
11
- import { GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS, getCreateA2aSessionInstructionAsync, fetchA2ASession, getSendA2aMessageInstruction, getUpdateA2aStatusInstruction, fetchMaybeA2ASession, fetchA2AMessage, fetchA2AStatus, getCreateCommunicationSessionInstructionAsync, getSendCommunicationMessageInstruction } from './chunk-COGZFWOT.js';
12
- export { GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS, getAddMessageReactionInstruction, getCancelEscrowInstruction, getChannelDecoder, getCompleteEscrowInstruction, getCreateEnhancedChannelInstructionAsync, getCreateEscrowInstructionAsync, getCreateWorkOrderInstruction, getDisputeEscrowInstruction, getEscrowDecoder, getJoinChannelInstruction, getLeaveChannelInstruction, getMessageDecoder, getProcessPartialRefundInstruction, getProcessPaymentInstruction, getRegisterAgentInstructionAsync, getRejectWorkDeliveryInstruction, getSendEnhancedMessageInstructionAsync, getSubmitWorkDeliveryInstruction, getUpdateChannelSettingsInstruction, getVerifyWorkDeliveryInstruction, getWorkDeliveryDecoder, getWorkOrderDecoder } from './chunk-COGZFWOT.js';
13
- export { deriveA2AMessagePda, deriveA2ASessionPda, deriveAgentPda, deriveAgentVerificationPda, deriveChannelPda, deriveEscrowPDA, deriveJobApplicationPda, deriveJobPostingPda, derivePaymentPda, deriveServiceListingPda, deriveServicePurchasePda, deriveUserRegistryPda, deriveWorkDeliveryPda, deriveWorkOrderPda, findProgramDerivedAddress } from './chunk-ASQXX4IT.js';
14
- import './chunk-RERCHKZP.js';
15
- import './chunk-RDDPOFR5.js';
16
- export { AgentType, ChannelType, ErrorCode, EscrowStatus, MessageType, isError, isSuccess, unwrap } from './chunk-SRS2SKFS.js';
17
- import { getAgentDecoder, fetchMaybeAgent, getCommunicationSessionDataDecoder } from './chunk-GMHIUK2R.js';
18
- export { AuctionStatus, AuctionType, DisputeStatus, ParticipantType, ProposalStatus, WorkOrderStatus, getAgentDecoder } from './chunk-GMHIUK2R.js';
19
- import { __export, __require } from './chunk-NSBPE2FW.js';
20
- import { createSolanaRpc, lamports, pipe, createTransactionMessage, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, signTransactionMessageWithSigners, getBase64EncodedWireTransaction, createKeyPairSignerFromBytes, generateKeyPairSigner, appendTransactionMessageInstruction, getProgramDerivedAddress, getBytesEncoder, getAddressEncoder } from '@solana/kit';
7
+ export { decrypt, elgamal_exports as elgamal, encrypt, generateKeypair, generateTransferProof, generateWithdrawProof, isWasmAvailable, loadWasmModule, wasm_bridge_exports as wasmBridge } from './chunk-VQZQCHUT.js';
8
+ import { getFeatureFlags, ClientEncryptionService } from './chunk-G7S6B6WB.js';
9
+ export { ClientEncryptionService, FeatureFlagManager, TokenExtension, TokenProgram, createDiscriminatorErrorMessage, createMigrationPlan, createMigrationReport, deriveAssociatedTokenAddress, deriveMultisigPda, deriveProposalPda, deriveSplTokenAssociatedTokenAddress, deriveToken2022AssociatedTokenAddress, detectTokenProgram, diagnoseAccountFromChain, diagnoseBatchFromChain, exportDiagnosticReport, extractLegacyData, formatTokenAmount, generateLocalPrivacyProof, getAllAssociatedTokenAddresses, getAssociatedTokenAccount, getConfidentialTransferConfig, getFeatureFlags, getInterestBearingConfig, getMigrationInstructions, getTokenProgramAddress, getTokenProgramFromAddress, getTokenProgramType, getTransferFeeConfig, hasConfidentialTransferExtension, hasInterestBearingExtension, hasTransferFeeExtension, inspectAccountData, isFeatureEnabled, isToken2022Mint, parseTokenAmount, runAccountDiagnostics, runBatchDiagnostics, safeDecodeAgent, simulateMigration, validateAccountDiscriminator, validateAssociatedTokenAddress, verifyLocalPrivacyProof } from './chunk-G7S6B6WB.js';
10
+ export { deriveAgentPda, deriveAgentVerificationPda, deriveUserRegistryPda, findProgramDerivedAddress } from './chunk-BF3IQ35I.js';
11
+ export { createAuthorizationMessage, createSignedAuthorization, deserializeAuthorization, generateNonce, getAuthorizationId, isAuthorizationExhausted, isAuthorizationExpired, serializeAuthorization, signAuthorizationMessage, validateAuthorizationNetwork, verifyAuthorizationSignature } from './chunk-BQDGRTVP.js';
12
+ import { init_reputation_tag_engine, init_reputation_tags } from './chunk-C5CDA3WX.js';
13
+ export { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, BadgeType, BehaviorTag, ComplianceTag, DEFAULT_TAG_DECAY, GhostSpeakSDKError, INSTRUCTION_MAPPINGS, IPFSClient, InstructionValidationError, NATIVE_MINT_ADDRESS, PRIVACY_CONSTANTS, PrivacyMode, PrivacyPresets, REPUTATION_CONSTANTS, ReputationTagEngine, ReputationTier, ScoreRange, SkillTag, TAG_CONSTANTS, TOKEN_2022_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, TagCategory, TagConfidenceLevel, VisibilityLevel, createAccountMismatchError, createErrorContext, debugInstructionCall, enhanceErrorMessage, enhanceTransactionError, extractInstructionName, generateAccountValidationError, getAccountRequirements, getInstructionMapping, getPDAAccounts, getRequiredSigners, getWritableAccounts, isKnownInstruction, logEnhancedError, validateInstructionAccounts, validatePreconditions, withEnhancedErrors, withEnhancedErrorsSync } from './chunk-C5CDA3WX.js';
14
+ export { getApproveDeliveryInstruction, getArbitrateDisputeInstruction, getCreateDidDocumentInstructionAsync, getCreateEscrowInstructionAsync, getDeactivateDidDocumentInstructionAsync, getFileDisputeInstruction, getGhostProtectEscrowDecoder, getInitializeStakingConfigInstructionAsync, getRegisterAgentInstructionAsync, getResolveDidDocumentInstructionAsync, getSlashStakeInstructionAsync, getStakeGhostInstructionAsync, getStakingAccountDecoder, getStakingConfigDecoder, getSubmitDeliveryInstruction, getUnstakeGhostInstructionAsync, getUpdateDidDocumentInstructionAsync, getUpdateReputationTagsInstructionAsync } from './chunk-S74EH3KD.js';
15
+ export { ProposalStatus, getAgentDecoder } from './chunk-IHVDQ4YI.js';
16
+ import './chunk-SFTSZ3LC.js';
17
+ import './chunk-JV2SWONF.js';
18
+ import './chunk-KB6CKIUK.js';
19
+ export { GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS } from './chunk-AL3HQN73.js';
20
+ export { AgentType, ChannelType, ErrorCode, EscrowStatus, MessageType, ParticipantType, isError, isSuccess, unwrap } from './chunk-SRS2SKFS.js';
21
+ export { CrossmintVCClient, GHOSTSPEAK_CREDENTIAL_TYPES } from './chunk-RIZZPLLB.js';
22
+ import { __require } from './chunk-UP2VWCW5.js';
23
+ import { createSolanaRpc, lamports, pipe, createTransactionMessage, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions, signTransactionMessageWithSigners, getBase64EncodedWireTransaction, createKeyPairSignerFromBytes, generateKeyPairSigner } from '@solana/kit';
21
24
  export { address, createKeyPairSignerFromBytes, createSolanaRpc, generateKeyPairSigner } from '@solana/kit';
22
- import { address } from '@solana/addresses';
23
- import { pipe as pipe$1 } from '@solana/functional';
24
25
  import { EventEmitter } from 'events';
25
- import { eq, sql, and, desc } from 'drizzle-orm';
26
- import { drizzle } from 'drizzle-orm/libsql';
27
- import { createClient } from '@libsql/client';
28
- import { sqliteTable, integer, text, index, real } from 'drizzle-orm/sqlite-core';
26
+ import { timingSafeEqual, createHmac } from 'crypto';
29
27
  import { getTransferSolInstruction } from '@solana-program/system';
30
28
  import { promises } from 'fs';
31
29
  import process2 from 'process';
@@ -34,3625 +32,696 @@ import tty from 'tty';
34
32
  import bs58 from 'bs58';
35
33
  import { sha256 } from '@noble/hashes/sha256';
36
34
  import { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
35
+ import { address } from '@solana/addresses';
37
36
 
38
- var X402Client = class extends EventEmitter {
39
- constructor(rpc, wallet) {
40
- super();
41
- this.rpc = rpc;
42
- this.wallet = wallet;
43
- }
44
- /**
45
- * Create an x402 payment request
46
- * Returns HTTP 402 compatible headers
47
- */
48
- createPaymentRequest(params) {
49
- if (!this.wallet) {
50
- throw new Error("Wallet required to create payment request");
51
- }
52
- const recipient = this.wallet.address;
53
- return {
54
- recipient,
55
- amount: params.amount,
56
- token: params.token,
57
- description: params.description,
58
- metadata: params.metadata,
59
- expiresAt: params.expiresAt ?? Date.now() + 3e5,
60
- // 5 minutes default
61
- requiresReceipt: true
62
- };
63
- }
64
- /**
65
- * Create HTTP 402 response headers
66
- */
67
- createPaymentHeaders(request) {
68
- const headers = {
69
- "X-Payment-Address": request.recipient,
70
- "X-Payment-Amount": request.amount.toString(),
71
- "X-Payment-Token": request.token,
72
- "X-Payment-Blockchain": "solana"
73
- };
74
- if (request.description) {
75
- headers["X-Payment-Description"] = request.description;
76
- }
77
- if (request.expiresAt) {
78
- headers["X-Payment-Expires-At"] = request.expiresAt.toString();
79
- }
80
- return headers;
37
+ init_reputation_tag_engine();
38
+
39
+ // src/modules/indexer/X402TransactionIndexer.ts
40
+ var X402TransactionIndexer = class {
41
+ rpc;
42
+ facilitatorAddress;
43
+ network;
44
+ batchSize;
45
+ constructor(config) {
46
+ this.rpc = config.rpc;
47
+ this.facilitatorAddress = config.facilitatorAddress;
48
+ this.network = config.network || "solana";
49
+ this.batchSize = config.batchSize || 100;
81
50
  }
51
+ // =====================================================
52
+ // PUBLIC METHODS
53
+ // =====================================================
82
54
  /**
83
- * Execute an x402 payment
55
+ * Poll for new x402 transactions since last sync
56
+ *
57
+ * @param lastSignature - Last processed signature (for pagination)
58
+ * @param limit - Maximum transactions to fetch
59
+ * @returns Array of parsed x402 payment data
84
60
  */
85
- async pay(request) {
86
- if (!this.wallet) {
87
- throw new Error("Wallet required to make payment");
88
- }
89
- if (request.amount <= 0n) {
90
- throw new Error("Payment amount must be greater than zero");
91
- }
92
- if (!request.recipient) {
93
- throw new Error("Payment recipient address is required");
94
- }
95
- if (!request.token) {
96
- throw new Error("Payment token address is required");
97
- }
98
- this.emit("payment_created", {
99
- type: "payment_created",
100
- request,
101
- timestamp: Date.now()
102
- });
61
+ async pollTransactions(lastSignature, limit) {
103
62
  try {
104
- const transferIx = await this.createTransferInstruction(
105
- request.recipient,
106
- request.amount,
107
- request.token
108
- ).catch((error) => {
109
- throw new Error(
110
- `Failed to create transfer instruction: ${error instanceof Error ? error.message : "Unknown error"}`
111
- );
112
- });
113
- const memoIx = this.createMemoInstruction(
114
- `x402:${request.description}:${JSON.stringify(request.metadata ?? {})}`
115
- );
116
- const { value: latestBlockhash } = await this.rpc.getLatestBlockhash().send().catch((error) => {
117
- throw new Error(
118
- `Failed to fetch latest blockhash: ${error instanceof Error ? error.message : "Unknown error"}`
119
- );
120
- });
121
- const feePayerAddress = this.wallet.address;
122
- const message = pipe$1(
123
- createTransactionMessage({ version: 0 }),
124
- (m) => setTransactionMessageFeePayer(feePayerAddress, m),
125
- (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
126
- (m) => appendTransactionMessageInstruction(transferIx, m),
127
- (m) => appendTransactionMessageInstruction(memoIx, m)
128
- );
129
- const signedTransaction = await signTransactionMessageWithSigners(message).catch((error) => {
130
- throw new Error(
131
- `Failed to sign transaction: ${error instanceof Error ? error.message : "Unknown error"}`
132
- );
133
- });
134
- const signature = await this.sendAndConfirmTransactionManually(signedTransaction).catch((error) => {
135
- const errorMessage = error instanceof Error ? error.message : String(error);
136
- if (errorMessage.includes("insufficient funds")) {
137
- throw new Error("Insufficient funds to complete payment");
138
- }
139
- if (errorMessage.includes("Blockhash not found")) {
140
- throw new Error("Transaction expired. Please retry the payment.");
141
- }
142
- if (errorMessage.includes("InvalidAccountOwner")) {
143
- throw new Error(
144
- "Associated Token Account not found or invalid. Please ensure the token account exists for both sender and recipient."
145
- );
63
+ const signatures = await this.getSignatures(lastSignature, limit);
64
+ if (signatures.length === 0) {
65
+ return [];
66
+ }
67
+ console.log(`[X402 Indexer] Found ${signatures.length} new transactions`);
68
+ const payments = [];
69
+ for (const sig of signatures) {
70
+ try {
71
+ const payment = await this.parseTransaction(sig.signature);
72
+ if (payment) {
73
+ payments.push(payment);
74
+ }
75
+ } catch (error) {
76
+ console.error(`[X402 Indexer] Failed to parse transaction ${sig.signature}:`, error);
146
77
  }
147
- throw new Error(
148
- `Transaction failed: ${errorMessage}`
149
- );
150
- });
151
- this.emit("payment_sent", {
152
- type: "payment_sent",
153
- signature,
154
- request,
155
- timestamp: Date.now()
156
- });
157
- const tx = await this.rpc.getTransaction(signature, {
158
- encoding: "jsonParsed",
159
- maxSupportedTransactionVersion: 0
160
- }).send().catch((error) => {
161
- console.warn("Payment succeeded but failed to fetch transaction details:", error);
162
- return null;
163
- });
164
- const receipt = {
165
- signature,
166
- recipient: request.recipient,
167
- amount: request.amount,
168
- token: request.token,
169
- timestamp: Date.now(),
170
- metadata: request.metadata,
171
- blockTime: tx?.blockTime ? Number(tx.blockTime) : void 0,
172
- slot: tx?.slot ?? void 0
173
- };
174
- this.emit("payment_confirmed", {
175
- type: "payment_confirmed",
176
- signature,
177
- request,
178
- receipt,
179
- timestamp: Date.now()
180
- });
181
- return receipt;
182
- } catch (error) {
183
- const errorMessage = error instanceof Error ? error.message : String(error);
184
- this.emit("payment_failed", {
185
- type: "payment_failed",
186
- request,
187
- error: errorMessage,
188
- timestamp: Date.now()
189
- });
190
- if (error instanceof Error) {
191
- throw error;
192
78
  }
193
- throw new Error(`Payment failed: ${String(error)}`);
79
+ console.log(`[X402 Indexer] Parsed ${payments.length} x402 payments`);
80
+ return payments;
81
+ } catch (error) {
82
+ console.error("[X402 Indexer] Failed to poll transactions:", error);
83
+ throw error;
194
84
  }
195
85
  }
196
86
  /**
197
- * Verify an x402 payment
87
+ * Parse a specific transaction signature
88
+ *
89
+ * @param signature - Transaction signature to parse
90
+ * @returns Parsed x402 payment data or null if not an x402 payment
198
91
  */
199
- async verifyPayment(signature) {
92
+ async parseTransaction(sig) {
200
93
  try {
201
- const tx = await this.rpc.getTransaction(signature, {
202
- encoding: "jsonParsed",
203
- maxSupportedTransactionVersion: 0
94
+ const txSignature = typeof sig === "string" ? sig : sig;
95
+ const response = await this.rpc.getTransaction(txSignature, {
96
+ maxSupportedTransactionVersion: 0,
97
+ encoding: "jsonParsed"
204
98
  }).send();
205
- if (!tx) {
206
- return {
207
- valid: false,
208
- error: "Transaction not found"
209
- };
99
+ if (!response || !response.transaction) {
100
+ return null;
210
101
  }
211
- if (tx.meta?.err !== null) {
212
- return {
213
- valid: false,
214
- error: "Transaction failed"
215
- };
102
+ const isX402 = this.isX402Payment(response);
103
+ if (!isX402) {
104
+ return null;
216
105
  }
217
- const receipt = this.parseTransactionReceipt(tx, signature);
218
- return {
219
- valid: true,
220
- receipt
221
- };
106
+ return this.extractPaymentData(response, typeof sig === "string" ? sig : String(sig));
222
107
  } catch (error) {
223
- return {
224
- valid: false,
225
- error: error instanceof Error ? error.message : "Unknown error"
226
- };
227
- }
228
- }
229
- /**
230
- * Verify payment for specific recipient and amount
231
- */
232
- async verifyPaymentDetails(params) {
233
- const result = await this.verifyPayment(params.signature);
234
- if (!result.valid || !result.receipt) {
235
- return result;
236
- }
237
- if (result.receipt.recipient !== params.expectedRecipient) {
238
- return {
239
- valid: false,
240
- error: "Recipient mismatch"
241
- };
242
- }
243
- if (result.receipt.amount !== params.expectedAmount) {
244
- return {
245
- valid: false,
246
- error: "Amount mismatch"
247
- };
248
- }
249
- if (result.receipt.token !== params.expectedToken) {
250
- return {
251
- valid: false,
252
- error: "Token mismatch"
253
- };
254
- }
255
- return {
256
- valid: true,
257
- receipt: result.receipt
258
- };
259
- }
260
- /**
261
- * Get payment status
262
- */
263
- async getPaymentStatus(signature) {
264
- try {
265
- const status = await this.rpc.getSignatureStatuses([signature]).send();
266
- if (!status.value[0]) {
267
- return { status: "not_found" };
268
- }
269
- const txStatus = status.value[0];
270
- if (txStatus.err) {
271
- return { status: "failed" };
272
- }
273
- if (txStatus.confirmationStatus === "finalized") {
274
- return { status: "finalized", confirmations: 32 };
275
- }
276
- if (txStatus.confirmationStatus === "confirmed") {
277
- return { status: "confirmed", confirmations: 1 };
278
- }
279
- return { status: "pending" };
280
- } catch {
281
- return { status: "not_found" };
108
+ console.error(`[X402 Indexer] Failed to fetch transaction ${sig}:`, error);
109
+ return null;
282
110
  }
283
111
  }
284
112
  // =====================================================
285
- // PRIVATE HELPER METHODS
113
+ // PRIVATE METHODS
286
114
  // =====================================================
287
- async createTransferInstruction(recipient, amount, token) {
288
- if (!this.wallet) {
289
- throw new Error("Wallet required");
290
- }
291
- const sourceAccount = await this.getAssociatedTokenAddress(
292
- this.wallet.address,
293
- token
294
- );
295
- const destinationAccount = await this.getAssociatedTokenAddress(
296
- recipient,
297
- token
298
- );
299
- const TOKEN_PROGRAM_ID = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
300
- const keys = [
301
- { address: sourceAccount, role: 1, isWritable: true, isSigner: false },
302
- { address: destinationAccount, role: 1, isWritable: true, isSigner: false },
303
- { address: this.wallet.address, role: 2, isWritable: false, isSigner: true }
304
- ];
305
- const data = new Uint8Array(9);
306
- data[0] = 3;
307
- const amountBytes = new BigUint64Array([amount]);
308
- data.set(new Uint8Array(amountBytes.buffer), 1);
309
- return {
310
- programAddress: TOKEN_PROGRAM_ID,
311
- accounts: keys,
312
- data
313
- };
314
- }
315
- createMemoInstruction(memo) {
316
- const MEMO_PROGRAM_ID = address("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
317
- return {
318
- programAddress: MEMO_PROGRAM_ID,
319
- accounts: [],
320
- data: new TextEncoder().encode(memo)
321
- };
322
- }
323
- async getAssociatedTokenAddress(owner, token) {
324
- try {
325
- const response = await this.rpc.getTokenAccountsByOwner(
326
- owner,
327
- { mint: token },
328
- { encoding: "jsonParsed" }
329
- ).send();
330
- if (response.value.length > 0) {
331
- return response.value[0].pubkey;
332
- }
333
- throw new Error(
334
- `Associated Token Account not found for owner ${owner} and mint ${token}. Please ensure the ATA is initialized before making payments. Use createAssociatedTokenAccountInstruction to create it.`
335
- );
336
- } catch (error) {
337
- if (error instanceof Error && error.message.includes("Associated Token Account not found")) {
338
- throw error;
339
- }
340
- throw new Error(
341
- `Failed to get Associated Token Account: ${error instanceof Error ? error.message : "Unknown error"}`
342
- );
343
- }
344
- }
345
- parseTransactionReceipt(tx, signature) {
346
- const instructions = tx.transaction?.message?.instructions ?? [];
347
- const transferInstruction = instructions.find((ix) => {
348
- const parsed2 = typeof ix.parsed === "object" ? ix.parsed : null;
349
- return ix.program === "spl-token" && parsed2?.type === "transfer";
350
- });
351
- if (!transferInstruction) {
352
- throw new Error("No SPL token transfer found in transaction");
353
- }
354
- const parsed = typeof transferInstruction.parsed === "object" ? transferInstruction.parsed : null;
355
- const transferInfo = parsed?.info;
356
- if (!transferInfo) {
357
- throw new Error("Failed to parse SPL token transfer instruction");
358
- }
359
- const recipient = address(transferInfo.destination ?? transferInfo.account ?? "");
360
- const amount = BigInt(transferInfo.amount ?? transferInfo.tokenAmount?.amount ?? "0");
361
- let tokenMint;
362
- const tokenBalances = tx.meta?.preTokenBalances ?? [];
363
- if (tokenBalances.length > 0) {
364
- tokenMint = address(String(tokenBalances[0].mint));
365
- } else {
366
- throw new Error("Failed to extract token mint from transaction");
367
- }
368
- const memoInstruction = instructions.find((ix) => {
369
- const programIdStr = typeof ix.programId === "string" ? ix.programId : ix.programId?.toString() ?? "";
370
- return ix.program === "spl-memo" || programIdStr === "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
371
- });
372
- let metadata;
373
- if (memoInstruction) {
374
- try {
375
- const parsedMemo = typeof memoInstruction.parsed === "string" ? memoInstruction.parsed : typeof memoInstruction.parsed === "object" ? memoInstruction.parsed?.data ?? "" : "";
376
- const memoText = parsedMemo || (memoInstruction.data ? new TextDecoder().decode(Buffer.from(memoInstruction.data, "base64")) : "");
377
- if (typeof memoText === "string" && memoText.startsWith("x402:")) {
378
- const parts = memoText.split(":");
379
- if (parts.length >= 3) {
380
- try {
381
- metadata = JSON.parse(parts[2]);
382
- } catch {
383
- }
384
- }
385
- }
386
- } catch {
387
- }
388
- }
389
- const blockTimeNum = tx.blockTime != null ? typeof tx.blockTime === "bigint" ? Number(tx.blockTime) : tx.blockTime : void 0;
390
- return {
391
- signature,
392
- recipient,
393
- amount,
394
- token: tokenMint,
395
- timestamp: blockTimeNum != null ? blockTimeNum * 1e3 : Date.now(),
396
- metadata,
397
- blockTime: blockTimeNum,
398
- slot: tx.slot
399
- };
400
- }
401
- /**
402
- * Send and confirm transaction manually (simplified implementation)
403
- * This is a workaround for the missing rpcSubscriptions dependency
404
- */
405
- async sendAndConfirmTransactionManually(signedTransaction) {
406
- const signatures = Object.values(signedTransaction.signatures);
407
- if (signatures.length === 0) {
408
- throw new Error("Transaction has no signatures");
409
- }
410
- const firstSig = signatures[0];
411
- if (!firstSig) {
412
- throw new Error("Transaction signature is null");
413
- }
414
- const signature = firstSig;
415
- const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
416
- await this.rpc.sendTransaction(wireTransaction).send();
417
- for (let i = 0; i < 30; i++) {
418
- const status = await this.rpc.getSignatureStatuses([signature]).send();
419
- if (status.value[0]?.confirmationStatus === "confirmed" || status.value[0]?.confirmationStatus === "finalized") {
420
- return signature;
421
- }
422
- await new Promise((resolve) => setTimeout(resolve, 1e3));
423
- }
424
- throw new Error("Transaction confirmation timeout");
425
- }
426
- };
427
- function createX402Client(rpcUrl, wallet) {
428
- const rpc = createSolanaRpc(rpcUrl);
429
- return new X402Client(rpc, wallet);
430
- }
431
-
432
- // src/database/config.ts
433
- var DEFAULT_CONFIG = {
434
- mode: process.env.NODE_ENV === "production" ? "production" : "development",
435
- pool: {
436
- max: 10,
437
- min: 2,
438
- connectionTimeoutMs: 5e3,
439
- idleTimeoutMs: 3e4
440
- }
441
- };
442
- function getTursoConfig() {
443
- const url = process.env.TURSO_DATABASE_URL ?? null;
444
- const authToken = process.env.TURSO_AUTH_TOKEN ?? null;
445
- const enabled = Boolean(url && authToken);
446
- if (!enabled && (url ?? authToken)) {
447
- console.warn(
448
- "[GhostSpeak Database] Incomplete Turso configuration detected. Both TURSO_DATABASE_URL and TURSO_AUTH_TOKEN are required. Falling back to on-chain only mode."
449
- );
450
- }
451
- return {
452
- url,
453
- authToken,
454
- enabled,
455
- ...DEFAULT_CONFIG
456
- };
457
- }
458
- function validateConfig(config) {
459
- if (!config.enabled) {
460
- return false;
461
- }
462
- if (!config.url || !config.authToken) {
463
- return false;
464
- }
465
- if (!config.url.startsWith("libsql://") && !config.url.startsWith("http://") && !config.url.startsWith("https://")) {
466
- console.error("[GhostSpeak Database] Invalid TURSO_DATABASE_URL format. Expected libsql://, http://, or https://");
467
- return false;
468
- }
469
- return true;
470
- }
471
-
472
- // src/database/connection.ts
473
- var DEFAULT_RETRY_CONFIG = {
474
- maxRetries: 3,
475
- initialDelayMs: 1e3,
476
- maxDelayMs: 1e4,
477
- backoffMultiplier: 2
478
- };
479
- var connectionState = {
480
- client: null,
481
- initialized: false,
482
- healthy: false,
483
- lastError: null,
484
- retryCount: 0,
485
- lastConnectAttempt: 0
486
- };
487
- function sleep(ms) {
488
- return new Promise((resolve) => setTimeout(resolve, ms));
489
- }
490
- function getRetryDelay(retryCount, config) {
491
- const delay = Math.min(
492
- config.initialDelayMs * Math.pow(config.backoffMultiplier, retryCount),
493
- config.maxDelayMs
494
- );
495
- return delay;
496
- }
497
- async function initializeConnection(config, retryConfig = DEFAULT_RETRY_CONFIG) {
498
- let lastError = null;
499
- for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
500
- try {
501
- connectionState.lastConnectAttempt = Date.now();
502
- if (attempt > 0) {
503
- const delay = getRetryDelay(attempt - 1, retryConfig);
504
- console.log(`[GhostSpeak Database] Retrying connection (attempt ${attempt + 1}/${retryConfig.maxRetries + 1}) after ${delay}ms...`);
505
- await sleep(delay);
506
- }
507
- const client = createClient({
508
- url: config.url,
509
- authToken: config.authToken
510
- });
511
- await client.execute("SELECT 1");
512
- console.log("[GhostSpeak Database] Connection established successfully");
513
- connectionState.retryCount = attempt;
514
- connectionState.healthy = true;
515
- connectionState.lastError = null;
516
- return client;
517
- } catch (error) {
518
- lastError = error instanceof Error ? error : new Error(String(error));
519
- console.error(`[GhostSpeak Database] Connection attempt ${attempt + 1} failed:`, lastError.message);
520
- if (attempt === retryConfig.maxRetries) {
521
- connectionState.healthy = false;
522
- connectionState.lastError = lastError;
523
- break;
524
- }
525
- }
526
- }
527
- throw new Error(
528
- `Failed to connect to Turso database after ${retryConfig.maxRetries + 1} attempts. Last error: ${lastError?.message ?? "Unknown error"}`
529
- );
530
- }
531
- async function getConnection() {
532
- const config = getTursoConfig();
533
- if (!config.enabled) {
534
- throw new Error(
535
- "Turso database not configured. Set TURSO_DATABASE_URL and TURSO_AUTH_TOKEN environment variables."
536
- );
537
- }
538
- if (!validateConfig(config)) {
539
- throw new Error("Invalid Turso database configuration");
540
- }
541
- if (connectionState.client && connectionState.healthy) {
542
- return connectionState.client;
543
- }
544
- if (!connectionState.initialized || !connectionState.healthy) {
545
- connectionState.initialized = true;
546
- connectionState.client = await initializeConnection(config);
547
- }
548
- return connectionState.client;
549
- }
550
- async function isAvailable() {
551
- const config = getTursoConfig();
552
- if (!config.enabled) {
553
- return false;
554
- }
555
- try {
556
- await getConnection();
557
- return true;
558
- } catch {
559
- return false;
560
- }
561
- }
562
-
563
- // src/database/schema/agents.ts
564
- var agents_exports = {};
565
- __export(agents_exports, {
566
- agentCapabilities: () => agentCapabilities,
567
- agentPricing: () => agentPricing,
568
- agents: () => agents
569
- });
570
- var agents = sqliteTable("agents", {
571
- // Primary key - Solana address
572
- agentAddress: text("agent_address").primaryKey(),
573
- // Basic info
574
- owner: text("owner").notNull(),
575
- name: text("name").notNull(),
576
- description: text("description").notNull(),
577
- // Reputation & stats
578
- reputationScore: integer("reputation_score").notNull().default(0),
579
- totalJobsCompleted: integer("total_jobs_completed").notNull().default(0),
580
- totalEarnings: text("total_earnings").notNull().default("0"),
581
- // Stored as text for u64
582
- // Status
583
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
584
- isVerified: integer("is_verified", { mode: "boolean" }).notNull().default(false),
585
- verificationTimestamp: integer("verification_timestamp").notNull().default(0),
586
- // Pricing
587
- originalPrice: text("original_price").notNull().default("0"),
588
- replicationFee: text("replication_fee").notNull().default("0"),
589
- // Configuration
590
- genomeHash: text("genome_hash").notNull().default(""),
591
- isReplicable: integer("is_replicable", { mode: "boolean" }).notNull().default(false),
592
- serviceEndpoint: text("service_endpoint").notNull().default(""),
593
- metadataUri: text("metadata_uri").notNull().default(""),
594
- // Framework & lineage
595
- frameworkOrigin: text("framework_origin").notNull().default(""),
596
- cnftMint: text("cnft_mint"),
597
- // Nullable
598
- merkleTree: text("merkle_tree"),
599
- // Nullable
600
- supportsA2a: integer("supports_a2a", { mode: "boolean" }).notNull().default(false),
601
- transferHook: text("transfer_hook"),
602
- // Nullable
603
- parentAgent: text("parent_agent"),
604
- // Nullable
605
- generation: integer("generation").notNull().default(0),
606
- // x402 Payment Protocol
607
- x402Enabled: integer("x402_enabled", { mode: "boolean" }).notNull().default(false),
608
- x402PaymentAddress: text("x402_payment_address").notNull(),
609
- x402PricePerCall: text("x402_price_per_call").notNull().default("0"),
610
- x402ServiceEndpoint: text("x402_service_endpoint").notNull().default(""),
611
- x402TotalPayments: text("x402_total_payments").notNull().default("0"),
612
- x402TotalCalls: text("x402_total_calls").notNull().default("0"),
613
- lastPaymentTimestamp: integer("last_payment_timestamp").notNull().default(0),
614
- // API Schema
615
- apiSpecUri: text("api_spec_uri").notNull().default(""),
616
- apiVersion: text("api_version").notNull().default(""),
617
- // Timestamps
618
- createdAt: integer("created_at").notNull(),
619
- updatedAt: integer("updated_at").notNull(),
620
- cachedAt: integer("cached_at").notNull(),
621
- // When cached from chain
622
- // Bump seed for PDA
623
- bump: integer("bump").notNull()
624
- }, (table) => ({
625
- // Indexes for common queries
626
- ownerIdx: index("idx_agents_owner").on(table.owner),
627
- x402EnabledIdx: index("idx_agents_x402_enabled").on(table.x402Enabled),
628
- reputationIdx: index("idx_agents_reputation").on(table.reputationScore),
629
- frameworkIdx: index("idx_agents_framework").on(table.frameworkOrigin),
630
- verifiedIdx: index("idx_agents_verified").on(table.isVerified),
631
- cachedAtIdx: index("idx_agents_cached_at").on(table.cachedAt)
632
- }));
633
- var agentCapabilities = sqliteTable("agent_capabilities", {
634
- id: integer("id").primaryKey({ autoIncrement: true }),
635
- agentAddress: text("agent_address").notNull().references(() => agents.agentAddress, { onDelete: "cascade" }),
636
- capability: text("capability").notNull()
637
- }, (table) => ({
638
- // Composite index for lookups
639
- agentCapabilityIdx: index("idx_agent_capability").on(table.agentAddress, table.capability)
640
- }));
641
- var agentPricing = sqliteTable("agent_pricing", {
642
- id: integer("id").primaryKey({ autoIncrement: true }),
643
- agentAddress: text("agent_address").notNull().references(() => agents.agentAddress, { onDelete: "cascade" }),
644
- tokenAddress: text("token_address").notNull(),
645
- // SPL token mint address
646
- decimals: integer("decimals").notNull(),
647
- symbol: text("symbol").notNull()
648
- }, (table) => ({
649
- // Index for token lookups
650
- agentTokenIdx: index("idx_agent_token").on(table.agentAddress, table.tokenAddress)
651
- }));
652
-
653
- // src/database/schema/transactions.ts
654
- var transactions_exports = {};
655
- __export(transactions_exports, {
656
- x402Transactions: () => x402Transactions
657
- });
658
- var x402Transactions = sqliteTable("x402_transactions", {
659
- // Primary key - Solana transaction signature
660
- signature: text("signature").primaryKey(),
661
- // Addresses
662
- agentAddress: text("agent_address").notNull(),
663
- // Agent that received payment
664
- payerAddress: text("payer_address").notNull(),
665
- // Who paid
666
- recipientAddress: text("recipient_address").notNull(),
667
- // Payment recipient
668
- // Payment details
669
- amount: text("amount").notNull(),
670
- // Amount in token's smallest unit (stored as text for bigint)
671
- tokenMint: text("token_mint").notNull(),
672
- // Token used for payment
673
- tokenDecimals: integer("token_decimals").notNull(),
674
- // Transaction status
675
- status: text("status").notNull().default("confirmed"),
676
- // 'confirmed', 'finalized', 'failed'
677
- // Timing
678
- blockTime: integer("block_time").notNull(),
679
- // Unix timestamp from Solana
680
- responseTimeMs: integer("response_time_ms"),
681
- // API response time (nullable)
682
- // Metadata
683
- metadataHash: text("metadata_hash"),
684
- // IPFS hash if applicable (nullable)
685
- // Timestamps
686
- createdAt: integer("created_at").notNull(),
687
- // When indexed
688
- updatedAt: integer("updated_at").notNull()
689
- // Last update
690
- }, (table) => ({
691
- // Indexes for common queries
692
- agentIdx: index("idx_tx_agent").on(table.agentAddress),
693
- payerIdx: index("idx_tx_payer").on(table.payerAddress),
694
- blockTimeIdx: index("idx_tx_block_time").on(table.blockTime),
695
- statusIdx: index("idx_tx_status").on(table.status),
696
- tokenIdx: index("idx_tx_token").on(table.tokenMint),
697
- // Composite index for agent + time range queries
698
- agentTimeIdx: index("idx_tx_agent_time").on(table.agentAddress, table.blockTime)
699
- }));
700
-
701
- // src/database/schema/analytics.ts
702
- var analytics_exports = {};
703
- __export(analytics_exports, {
704
- agentAnalytics: () => agentAnalytics,
705
- dailyMetrics: () => dailyMetrics,
706
- marketAnalytics: () => marketAnalytics
707
- });
708
- var agentAnalytics = sqliteTable("agent_analytics", {
709
- // Primary key - agent address
710
- agentAddress: text("agent_address").primaryKey(),
711
- // Revenue metrics
712
- totalRevenue: text("total_revenue").notNull().default("0"),
713
- // Stored as text for bigint
714
- // Transaction metrics
715
- totalTransactions: integer("total_transactions").notNull().default(0),
716
- successfulTransactions: integer("successful_transactions").notNull().default(0),
717
- successRate: real("success_rate").notNull().default(0),
718
- // Percentage 0-100
719
- // Quality metrics
720
- averageRating: real("average_rating").notNull().default(0),
721
- averageResponseTimeMs: integer("average_response_time_ms").notNull().default(0),
722
- // Activity
723
- lastTransactionAt: integer("last_transaction_at"),
724
- // Unix timestamp (nullable)
725
- // Timestamp
726
- updatedAt: integer("updated_at").notNull()
727
- }, (table) => ({
728
- updatedAtIdx: index("idx_agent_analytics_updated").on(table.updatedAt)
729
- }));
730
- var marketAnalytics = sqliteTable("market_analytics", {
731
- id: integer("id").primaryKey({ autoIncrement: true }),
732
- // Date for this snapshot
733
- metricDate: text("metric_date").notNull().unique(),
734
- // ISO date string (YYYY-MM-DD)
735
- // Volume metrics
736
- totalVolume: text("total_volume").notNull().default("0"),
737
- // Stored as text for bigint
738
- totalTransactions: integer("total_transactions").notNull().default(0),
739
- // Agent metrics
740
- activeAgentsCount: integer("active_agents_count").notNull().default(0),
741
- // Price metrics
742
- averagePrice: text("average_price").notNull().default("0"),
743
- // Average transaction amount
744
- // User metrics
745
- uniquePayers: integer("unique_payers").notNull().default(0),
746
- // Timestamp
747
- updatedAt: integer("updated_at").notNull()
748
- }, (table) => ({
749
- dateIdx: index("idx_market_analytics_date").on(table.metricDate)
750
- }));
751
- var dailyMetrics = sqliteTable("daily_metrics", {
752
- id: integer("id").primaryKey({ autoIncrement: true }),
753
- // Date and metric type
754
- metricDate: text("metric_date").notNull(),
755
- // ISO date (YYYY-MM-DD)
756
- metricType: text("metric_type").notNull(),
757
- // 'agent_revenue', 'market_volume', etc.
758
- // Optional agent address (null for market-wide metrics)
759
- agentAddress: text("agent_address"),
760
- // Nullable
761
- // Metric value and metadata
762
- value: text("value").notNull(),
763
- // Metric value as text (supports bigint)
764
- metadata: text("metadata"),
765
- // JSON string for additional data (nullable)
766
- // Timestamp
767
- createdAt: integer("created_at").notNull()
768
- }, (table) => ({
769
- // Composite index for date + type queries
770
- dateTypeIdx: index("idx_daily_metrics_date_type").on(table.metricDate, table.metricType),
771
- // Index for agent-specific queries
772
- agentIdx: index("idx_daily_metrics_agent").on(table.agentAddress),
773
- // Index for time-series queries
774
- dateIdx: index("idx_daily_metrics_date").on(table.metricDate)
775
- }));
776
-
777
- // src/database/schema/facilitators.ts
778
- var facilitators_exports = {};
779
- __export(facilitators_exports, {
780
- facilitatorApiKeys: () => facilitatorApiKeys,
781
- facilitatorHealthHistory: () => facilitatorHealthHistory,
782
- facilitators: () => facilitators
783
- });
784
- var facilitators = sqliteTable(
785
- "facilitators",
786
- {
787
- // Primary key - unique facilitator ID
788
- id: text("id").primaryKey(),
789
- // Basic info
790
- name: text("name").notNull(),
791
- description: text("description"),
792
- logo: text("logo"),
793
- website: text("website"),
794
- // Network configuration (JSON serialized)
795
- networks: text("networks").notNull(),
796
- // JSON array of Network enum values
797
- // Address configuration (JSON serialized)
798
- addresses: text("addresses").notNull(),
799
- // JSON Record<Network, FacilitatorAddress[]>
800
- // Endpoints
801
- discoveryUrl: text("discovery_url"),
802
- settleUrl: text("settle_url").notNull(),
803
- verifyUrl: text("verify_url").notNull(),
804
- // API configuration
805
- requiresApiKey: integer("requires_api_key", { mode: "boolean" }).notNull().default(false),
806
- apiKeyHeader: text("api_key_header"),
807
- // Status
808
- enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
809
- // Health metrics
810
- lastHealthCheck: integer("last_health_check"),
811
- // Unix timestamp
812
- healthStatus: text("health_status").default("unknown"),
813
- // healthy, degraded, unhealthy, unknown
814
- latencyMs: real("latency_ms"),
815
- uptimePercent: real("uptime_percent"),
816
- totalRequests: integer("total_requests").notNull().default(0),
817
- successfulRequests: integer("successful_requests").notNull().default(0),
818
- failedRequests: integer("failed_requests").notNull().default(0),
819
- // Timestamps
820
- createdAt: integer("created_at").notNull().default(0),
821
- updatedAt: integer("updated_at").notNull().default(0)
822
- },
823
- (table) => ({
824
- enabledIdx: index("facilitators_enabled_idx").on(table.enabled),
825
- healthStatusIdx: index("facilitators_health_status_idx").on(table.healthStatus)
826
- })
827
- );
828
- var facilitatorApiKeys = sqliteTable(
829
- "facilitator_api_keys",
830
- {
831
- // Composite key
832
- id: text("id").primaryKey(),
833
- // UUID or generated
834
- // Foreign keys
835
- facilitatorId: text("facilitator_id").notNull().references(() => facilitators.id),
836
- userId: text("user_id").notNull(),
837
- // User or wallet address
838
- // Key storage (encrypted)
839
- encryptedApiKey: text("encrypted_api_key").notNull(),
840
- keyLabel: text("key_label"),
841
- // User-friendly label
842
- // Metadata
843
- lastUsed: integer("last_used"),
844
- // Unix timestamp
845
- usageCount: integer("usage_count").notNull().default(0),
846
- // Timestamps
847
- createdAt: integer("created_at").notNull().default(0),
848
- updatedAt: integer("updated_at").notNull().default(0)
849
- },
850
- (table) => ({
851
- facilitatorUserIdx: index("api_keys_facilitator_user_idx").on(
852
- table.facilitatorId,
853
- table.userId
854
- )
855
- })
856
- );
857
- var facilitatorHealthHistory = sqliteTable(
858
- "facilitator_health_history",
859
- {
860
- // Primary key
861
- id: text("id").primaryKey(),
862
- // UUID
863
- // Foreign key
864
- facilitatorId: text("facilitator_id").notNull().references(() => facilitators.id),
865
- // Health check result
866
- status: text("status").notNull(),
867
- // healthy, degraded, unhealthy
868
- latencyMs: real("latency_ms").notNull(),
869
- errorMessage: text("error_message"),
870
- // Network-specific results (JSON serialized)
871
- networkResults: text("network_results"),
872
- // JSON array of network health
873
- // Timestamp
874
- checkedAt: integer("checked_at").notNull()
875
- },
876
- (table) => ({
877
- facilitatorTimeIdx: index("health_history_facilitator_time_idx").on(
878
- table.facilitatorId,
879
- table.checkedAt
880
- )
881
- })
882
- );
883
-
884
- // src/database/schema/resources.ts
885
- var resources_exports = {};
886
- __export(resources_exports, {
887
- resourceAccepts: () => resourceAccepts,
888
- resourceOrigins: () => resourceOrigins,
889
- resourcePingHistory: () => resourcePingHistory,
890
- resourceTags: () => resourceTags,
891
- resources: () => resources
892
- });
893
- var resourceOrigins = sqliteTable(
894
- "resource_origins",
895
- {
896
- // Primary key - UUID
897
- id: text("id").primaryKey(),
898
- // Origin URL (e.g., https://api.example.com)
899
- origin: text("origin").notNull().unique(),
900
- // Metadata from scraping
901
- name: text("name"),
902
- description: text("description"),
903
- faviconUrl: text("favicon_url"),
904
- ogImageUrl: text("og_image_url"),
905
- ogTitle: text("og_title"),
906
- ogDescription: text("og_description"),
907
- // Contact/attribution
908
- contactEmail: text("contact_email"),
909
- twitterHandle: text("twitter_handle"),
910
- githubRepo: text("github_repo"),
911
- // Verification
912
- isVerified: integer("is_verified", { mode: "boolean" }).notNull().default(false),
913
- verifiedAt: integer("verified_at"),
914
- verifiedBy: text("verified_by"),
915
- // Timestamps
916
- createdAt: integer("created_at").notNull().default(0),
917
- updatedAt: integer("updated_at").notNull().default(0),
918
- lastScrapedAt: integer("last_scraped_at")
919
- },
920
- (table) => ({
921
- originIdx: index("resource_origins_origin_idx").on(table.origin)
922
- })
923
- );
924
- var resources = sqliteTable(
925
- "resources",
926
- {
927
- // Primary key - UUID
928
- id: text("id").primaryKey(),
929
- // Resource URL (full endpoint URL)
930
- url: text("url").notNull().unique(),
931
- // Type of resource
932
- type: text("type").notNull().default("http"),
933
- // http, websocket, grpc
934
- // x402 protocol version
935
- x402Version: text("x402_version"),
936
- // Foreign keys
937
- originId: text("origin_id").references(() => resourceOrigins.id),
938
- facilitatorId: text("facilitator_id").references(() => facilitators.id),
939
- // Payment requirements (JSON serialized PaymentRequirement[])
940
- accepts: text("accepts").notNull(),
941
- // JSON array
942
- // Pricing
943
- maxAmount: text("max_amount"),
944
- // bigint as string
945
- minAmount: text("min_amount"),
946
- // bigint as string
947
- currency: text("currency").default("USDC"),
948
- // Enhanced schema for AI integration (JSON Schema)
949
- inputSchema: text("input_schema"),
950
- // JSON Schema for input
951
- outputSchema: text("output_schema"),
952
- // JSON Schema for output
953
- examplesJson: text("examples_json"),
954
- // JSON array of { input, output }
955
- // Metadata
956
- name: text("name"),
957
- description: text("description"),
958
- tags: text("tags"),
959
- // JSON array of strings
960
- capabilities: text("capabilities"),
961
- // JSON array of capabilities
962
- category: text("category"),
963
- // AI category
964
- // HTTP metadata
965
- httpMethod: text("http_method").default("POST"),
966
- contentType: text("content_type").default("application/json"),
967
- authType: text("auth_type"),
968
- // none, bearer, api_key, x402
969
- // Status
970
- isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
971
- isVerified: integer("is_verified", { mode: "boolean" }).notNull().default(false),
972
- lastPingAt: integer("last_ping_at"),
973
- lastPingStatus: integer("last_ping_status"),
974
- // HTTP status code
975
- lastPingLatencyMs: real("last_ping_latency_ms"),
976
- consecutiveFailures: integer("consecutive_failures").notNull().default(0),
977
- // Discovery source
978
- discoveredFrom: text("discovered_from"),
979
- // facilitator_id or 'manual'
980
- discoveredAt: integer("discovered_at"),
981
- // AI labeling
982
- aiGeneratedTags: text("ai_generated_tags"),
983
- // JSON array
984
- aiLabeledAt: integer("ai_labeled_at"),
985
- // Timestamps
986
- createdAt: integer("created_at").notNull().default(0),
987
- updatedAt: integer("updated_at").notNull().default(0)
988
- },
989
- (table) => ({
990
- originIdx: index("resources_origin_idx").on(table.originId),
991
- facilitatorIdx: index("resources_facilitator_idx").on(table.facilitatorId),
992
- activeIdx: index("resources_active_idx").on(table.isActive),
993
- categoryIdx: index("resources_category_idx").on(table.category)
994
- })
995
- );
996
- var resourceTags = sqliteTable(
997
- "resource_tags",
998
- {
999
- // Composite key
1000
- id: text("id").primaryKey(),
1001
- // UUID
1002
- // Foreign key
1003
- resourceId: text("resource_id").notNull().references(() => resources.id),
1004
- // Tag
1005
- tag: text("tag").notNull(),
1006
- isAiGenerated: integer("is_ai_generated", { mode: "boolean" }).notNull().default(false),
1007
- // Timestamps
1008
- createdAt: integer("created_at").notNull().default(0)
1009
- },
1010
- (table) => ({
1011
- resourceIdx: index("resource_tags_resource_idx").on(table.resourceId),
1012
- tagIdx: index("resource_tags_tag_idx").on(table.tag)
1013
- })
1014
- );
1015
- var resourcePingHistory = sqliteTable(
1016
- "resource_ping_history",
1017
- {
1018
- // Primary key - UUID
1019
- id: text("id").primaryKey(),
1020
- // Foreign key
1021
- resourceId: text("resource_id").notNull().references(() => resources.id),
1022
- // Ping result
1023
- statusCode: integer("status_code"),
1024
- latencyMs: real("latency_ms"),
1025
- success: integer("success", { mode: "boolean" }).notNull(),
1026
- errorMessage: text("error_message"),
1027
- // x402 response validation
1028
- hasValidX402: integer("has_valid_x402", { mode: "boolean" }),
1029
- x402ParseError: text("x402_parse_error"),
1030
- // Response details
1031
- responseBodySize: integer("response_body_size"),
1032
- contentType: text("content_type"),
1033
- // Timestamp
1034
- pingedAt: integer("pinged_at").notNull()
1035
- },
1036
- (table) => ({
1037
- resourceTimeIdx: index("ping_history_resource_time_idx").on(
1038
- table.resourceId,
1039
- table.pingedAt
1040
- )
1041
- })
1042
- );
1043
- var resourceAccepts = sqliteTable(
1044
- "resource_accepts",
1045
- {
1046
- // Primary key - UUID
1047
- id: text("id").primaryKey(),
1048
- // Foreign key
1049
- resourceId: text("resource_id").notNull().references(() => resources.id),
1050
- // Payment requirement fields
1051
- scheme: text("scheme").notNull(),
1052
- // exact, upto, base, tiered
1053
- network: text("network").notNull(),
1054
- // solana, base, polygon
1055
- maxAmountRequired: text("max_amount_required").notNull(),
1056
- // bigint as string
1057
- payTo: text("pay_to").notNull(),
1058
- // facilitator address
1059
- asset: text("asset").notNull(),
1060
- // token address
1061
- maxTimeoutSeconds: integer("max_timeout_seconds"),
1062
- description: text("description"),
1063
- mimeType: text("mime_type"),
1064
- // Extra fields (JSON)
1065
- extra: text("extra"),
1066
- // Timestamps
1067
- createdAt: integer("created_at").notNull().default(0),
1068
- updatedAt: integer("updated_at").notNull().default(0)
1069
- },
1070
- (table) => ({
1071
- resourceIdx: index("resource_accepts_resource_idx").on(table.resourceId),
1072
- networkIdx: index("resource_accepts_network_idx").on(table.network),
1073
- assetIdx: index("resource_accepts_asset_idx").on(table.asset)
1074
- })
1075
- );
1076
-
1077
- // src/database/schema/resourceMetrics.ts
1078
- var resourceMetrics_exports = {};
1079
- __export(resourceMetrics_exports, {
1080
- TIME_WINDOWS: () => TIME_WINDOWS,
1081
- globalMetrics: () => globalMetrics,
1082
- resourceMetrics: () => resourceMetrics,
1083
- resourceOriginMetrics: () => resourceOriginMetrics
1084
- });
1085
- var TIME_WINDOWS = ["1h", "6h", "24h", "3d", "7d", "15d", "30d", "all"];
1086
- var resourceMetrics = sqliteTable(
1087
- "resource_metrics",
1088
- {
1089
- // Primary key
1090
- id: text("id").primaryKey(),
1091
- // Foreign key to resource
1092
- resourceId: text("resource_id").notNull().references(() => resources.id),
1093
- // Snapshot timestamp
1094
- createdAt: integer("created_at").notNull(),
1095
- // =========================================================
1096
- // REQUEST COUNTS (8 time windows each)
1097
- // =========================================================
1098
- // Total requests
1099
- totalRequests1h: integer("total_requests_1h").notNull().default(0),
1100
- totalRequests6h: integer("total_requests_6h").notNull().default(0),
1101
- totalRequests24h: integer("total_requests_24h").notNull().default(0),
1102
- totalRequests3d: integer("total_requests_3d").notNull().default(0),
1103
- totalRequests7d: integer("total_requests_7d").notNull().default(0),
1104
- totalRequests15d: integer("total_requests_15d").notNull().default(0),
1105
- totalRequests30d: integer("total_requests_30d").notNull().default(0),
1106
- totalRequestsAll: integer("total_requests_all").notNull().default(0),
1107
- // Successful requests (2xx)
1108
- successCount1h: integer("success_count_1h").notNull().default(0),
1109
- successCount6h: integer("success_count_6h").notNull().default(0),
1110
- successCount24h: integer("success_count_24h").notNull().default(0),
1111
- successCount3d: integer("success_count_3d").notNull().default(0),
1112
- successCount7d: integer("success_count_7d").notNull().default(0),
1113
- successCount15d: integer("success_count_15d").notNull().default(0),
1114
- successCount30d: integer("success_count_30d").notNull().default(0),
1115
- successCountAll: integer("success_count_all").notNull().default(0),
1116
- // Failed requests (4xx, 5xx)
1117
- failureCount1h: integer("failure_count_1h").notNull().default(0),
1118
- failureCount6h: integer("failure_count_6h").notNull().default(0),
1119
- failureCount24h: integer("failure_count_24h").notNull().default(0),
1120
- failureCount3d: integer("failure_count_3d").notNull().default(0),
1121
- failureCount7d: integer("failure_count_7d").notNull().default(0),
1122
- failureCount15d: integer("failure_count_15d").notNull().default(0),
1123
- failureCount30d: integer("failure_count_30d").notNull().default(0),
1124
- failureCountAll: integer("failure_count_all").notNull().default(0),
1125
- // =========================================================
1126
- // LATENCY PERCENTILES (p50, p90, p99 for each window)
1127
- // =========================================================
1128
- // P50 (median) latency in ms
1129
- latencyP50_1h: real("latency_p50_1h"),
1130
- latencyP50_6h: real("latency_p50_6h"),
1131
- latencyP50_24h: real("latency_p50_24h"),
1132
- latencyP50_3d: real("latency_p50_3d"),
1133
- latencyP50_7d: real("latency_p50_7d"),
1134
- latencyP50_15d: real("latency_p50_15d"),
1135
- latencyP50_30d: real("latency_p50_30d"),
1136
- latencyP50All: real("latency_p50_all"),
1137
- // P90 latency in ms
1138
- latencyP90_1h: real("latency_p90_1h"),
1139
- latencyP90_6h: real("latency_p90_6h"),
1140
- latencyP90_24h: real("latency_p90_24h"),
1141
- latencyP90_3d: real("latency_p90_3d"),
1142
- latencyP90_7d: real("latency_p90_7d"),
1143
- latencyP90_15d: real("latency_p90_15d"),
1144
- latencyP90_30d: real("latency_p90_30d"),
1145
- latencyP90All: real("latency_p90_all"),
1146
- // P99 latency in ms
1147
- latencyP99_1h: real("latency_p99_1h"),
1148
- latencyP99_6h: real("latency_p99_6h"),
1149
- latencyP99_24h: real("latency_p99_24h"),
1150
- latencyP99_3d: real("latency_p99_3d"),
1151
- latencyP99_7d: real("latency_p99_7d"),
1152
- latencyP99_15d: real("latency_p99_15d"),
1153
- latencyP99_30d: real("latency_p99_30d"),
1154
- latencyP99All: real("latency_p99_all"),
1155
- // =========================================================
1156
- // STATUS CODE DISTRIBUTION
1157
- // =========================================================
1158
- // 2xx responses
1159
- status2xx1h: integer("status_2xx_1h").notNull().default(0),
1160
- status2xx24h: integer("status_2xx_24h").notNull().default(0),
1161
- status2xx7d: integer("status_2xx_7d").notNull().default(0),
1162
- status2xxAll: integer("status_2xx_all").notNull().default(0),
1163
- // 3xx responses
1164
- status3xx1h: integer("status_3xx_1h").notNull().default(0),
1165
- status3xx24h: integer("status_3xx_24h").notNull().default(0),
1166
- status3xx7d: integer("status_3xx_7d").notNull().default(0),
1167
- status3xxAll: integer("status_3xx_all").notNull().default(0),
1168
- // 4xx responses
1169
- status4xx1h: integer("status_4xx_1h").notNull().default(0),
1170
- status4xx24h: integer("status_4xx_24h").notNull().default(0),
1171
- status4xx7d: integer("status_4xx_7d").notNull().default(0),
1172
- status4xxAll: integer("status_4xx_all").notNull().default(0),
1173
- // 5xx responses
1174
- status5xx1h: integer("status_5xx_1h").notNull().default(0),
1175
- status5xx24h: integer("status_5xx_24h").notNull().default(0),
1176
- status5xx7d: integer("status_5xx_7d").notNull().default(0),
1177
- status5xxAll: integer("status_5xx_all").notNull().default(0),
1178
- // =========================================================
1179
- // UPTIME & AVAILABILITY
1180
- // =========================================================
1181
- // Uptime percentage (0-100)
1182
- uptimePercent1h: real("uptime_percent_1h"),
1183
- uptimePercent24h: real("uptime_percent_24h"),
1184
- uptimePercent7d: real("uptime_percent_7d"),
1185
- uptimePercent30d: real("uptime_percent_30d"),
1186
- uptimePercentAll: real("uptime_percent_all"),
1187
- // Number of outages
1188
- outageCount1h: integer("outage_count_1h").notNull().default(0),
1189
- outageCount24h: integer("outage_count_24h").notNull().default(0),
1190
- outageCount7d: integer("outage_count_7d").notNull().default(0),
1191
- outageCount30d: integer("outage_count_30d").notNull().default(0),
1192
- // =========================================================
1193
- // PAYMENT METRICS
1194
- // =========================================================
1195
- // Total payment volume (stored as text for bigint)
1196
- paymentVolume1h: text("payment_volume_1h").notNull().default("0"),
1197
- paymentVolume24h: text("payment_volume_24h").notNull().default("0"),
1198
- paymentVolume7d: text("payment_volume_7d").notNull().default("0"),
1199
- paymentVolume30d: text("payment_volume_30d").notNull().default("0"),
1200
- paymentVolumeAll: text("payment_volume_all").notNull().default("0"),
1201
- // Number of payments
1202
- paymentCount1h: integer("payment_count_1h").notNull().default(0),
1203
- paymentCount24h: integer("payment_count_24h").notNull().default(0),
1204
- paymentCount7d: integer("payment_count_7d").notNull().default(0),
1205
- paymentCount30d: integer("payment_count_30d").notNull().default(0),
1206
- paymentCountAll: integer("payment_count_all").notNull().default(0),
1207
- // Average payment amount
1208
- avgPayment1h: text("avg_payment_1h"),
1209
- avgPayment24h: text("avg_payment_24h"),
1210
- avgPayment7d: text("avg_payment_7d"),
1211
- avgPaymentAll: text("avg_payment_all"),
1212
- // Unique payers
1213
- uniquePayers1h: integer("unique_payers_1h").notNull().default(0),
1214
- uniquePayers24h: integer("unique_payers_24h").notNull().default(0),
1215
- uniquePayers7d: integer("unique_payers_7d").notNull().default(0),
1216
- uniquePayersAll: integer("unique_payers_all").notNull().default(0)
1217
- },
1218
- (table) => ({
1219
- resourceIdx: index("resource_metrics_resource_idx").on(table.resourceId),
1220
- createdAtIdx: index("resource_metrics_created_at_idx").on(table.createdAt),
1221
- resourceCreatedIdx: index("resource_metrics_resource_created_idx").on(
1222
- table.resourceId,
1223
- table.createdAt
1224
- )
1225
- })
1226
- );
1227
- var resourceOriginMetrics = sqliteTable(
1228
- "resource_origin_metrics",
1229
- {
1230
- // Primary key
1231
- id: text("id").primaryKey(),
1232
- // Foreign key to origin
1233
- originId: text("origin_id").notNull().references(() => resourceOrigins.id),
1234
- // Snapshot timestamp
1235
- createdAt: integer("created_at").notNull(),
1236
- // Resource count
1237
- resourceCount: integer("resource_count").notNull().default(0),
1238
- activeResourceCount: integer("active_resource_count").notNull().default(0),
1239
- // Aggregated request counts
1240
- totalRequests1h: integer("total_requests_1h").notNull().default(0),
1241
- totalRequests24h: integer("total_requests_24h").notNull().default(0),
1242
- totalRequests7d: integer("total_requests_7d").notNull().default(0),
1243
- totalRequestsAll: integer("total_requests_all").notNull().default(0),
1244
- // Aggregated success counts
1245
- successCount1h: integer("success_count_1h").notNull().default(0),
1246
- successCount24h: integer("success_count_24h").notNull().default(0),
1247
- successCount7d: integer("success_count_7d").notNull().default(0),
1248
- successCountAll: integer("success_count_all").notNull().default(0),
1249
- // Aggregated failure counts
1250
- failureCount1h: integer("failure_count_1h").notNull().default(0),
1251
- failureCount24h: integer("failure_count_24h").notNull().default(0),
1252
- failureCount7d: integer("failure_count_7d").notNull().default(0),
1253
- failureCountAll: integer("failure_count_all").notNull().default(0),
1254
- // Average latency across resources
1255
- avgLatencyP50_1h: real("avg_latency_p50_1h"),
1256
- avgLatencyP50_24h: real("avg_latency_p50_24h"),
1257
- avgLatencyP50_7d: real("avg_latency_p50_7d"),
1258
- avgLatencyP50All: real("avg_latency_p50_all"),
1259
- avgLatencyP90_1h: real("avg_latency_p90_1h"),
1260
- avgLatencyP90_24h: real("avg_latency_p90_24h"),
1261
- avgLatencyP90_7d: real("avg_latency_p90_7d"),
1262
- avgLatencyP90All: real("avg_latency_p90_all"),
1263
- // Aggregated uptime
1264
- avgUptimePercent1h: real("avg_uptime_percent_1h"),
1265
- avgUptimePercent24h: real("avg_uptime_percent_24h"),
1266
- avgUptimePercent7d: real("avg_uptime_percent_7d"),
1267
- avgUptimePercentAll: real("avg_uptime_percent_all"),
1268
- // Aggregated payment metrics
1269
- paymentVolume1h: text("payment_volume_1h").notNull().default("0"),
1270
- paymentVolume24h: text("payment_volume_24h").notNull().default("0"),
1271
- paymentVolume7d: text("payment_volume_7d").notNull().default("0"),
1272
- paymentVolumeAll: text("payment_volume_all").notNull().default("0"),
1273
- paymentCount1h: integer("payment_count_1h").notNull().default(0),
1274
- paymentCount24h: integer("payment_count_24h").notNull().default(0),
1275
- paymentCount7d: integer("payment_count_7d").notNull().default(0),
1276
- paymentCountAll: integer("payment_count_all").notNull().default(0)
1277
- },
1278
- (table) => ({
1279
- originIdx: index("origin_metrics_origin_idx").on(table.originId),
1280
- createdAtIdx: index("origin_metrics_created_at_idx").on(table.createdAt)
1281
- })
1282
- );
1283
- var globalMetrics = sqliteTable("global_metrics", {
1284
- // Primary key (single row, use 'global')
1285
- id: text("id").primaryKey(),
1286
- // Snapshot timestamp
1287
- createdAt: integer("created_at").notNull(),
1288
- // Resource counts
1289
- totalResources: integer("total_resources").notNull().default(0),
1290
- activeResources: integer("active_resources").notNull().default(0),
1291
- totalOrigins: integer("total_origins").notNull().default(0),
1292
- totalFacilitators: integer("total_facilitators").notNull().default(0),
1293
- // Request aggregates
1294
- totalRequests1h: integer("total_requests_1h").notNull().default(0),
1295
- totalRequests24h: integer("total_requests_24h").notNull().default(0),
1296
- totalRequests7d: integer("total_requests_7d").notNull().default(0),
1297
- totalRequestsAll: integer("total_requests_all").notNull().default(0),
1298
- // Payment aggregates
1299
- paymentVolume1h: text("payment_volume_1h").notNull().default("0"),
1300
- paymentVolume24h: text("payment_volume_24h").notNull().default("0"),
1301
- paymentVolume7d: text("payment_volume_7d").notNull().default("0"),
1302
- paymentVolumeAll: text("payment_volume_all").notNull().default("0"),
1303
- paymentCount1h: integer("payment_count_1h").notNull().default(0),
1304
- paymentCount24h: integer("payment_count_24h").notNull().default(0),
1305
- paymentCount7d: integer("payment_count_7d").notNull().default(0),
1306
- paymentCountAll: integer("payment_count_all").notNull().default(0),
1307
- // Unique users
1308
- uniquePayers1h: integer("unique_payers_1h").notNull().default(0),
1309
- uniquePayers24h: integer("unique_payers_24h").notNull().default(0),
1310
- uniquePayers7d: integer("unique_payers_7d").notNull().default(0),
1311
- uniquePayersAll: integer("unique_payers_all").notNull().default(0),
1312
- // Network breakdown (JSON)
1313
- networkBreakdown: text("network_breakdown"),
1314
- // JSON object
1315
- // Top performers (JSON arrays)
1316
- topResourcesByVolume: text("top_resources_by_volume"),
1317
- // JSON array
1318
- topResourcesByRequests: text("top_resources_by_requests"),
1319
- // JSON array
1320
- topOriginsByVolume: text("top_origins_by_volume")
1321
- // JSON array
1322
- });
1323
-
1324
- // src/database/schema/index.ts
1325
- var schema = {
1326
- ...agents_exports,
1327
- ...transactions_exports,
1328
- ...analytics_exports,
1329
- ...facilitators_exports,
1330
- ...resources_exports,
1331
- ...resourceMetrics_exports
1332
- };
1333
-
1334
- // src/database/db.ts
1335
- async function getDb() {
1336
- const client = await getConnection();
1337
- return drizzle(client, { schema });
1338
- }
1339
-
1340
- // src/database/services/AgentCacheService.ts
1341
- var AgentCacheService = class _AgentCacheService {
1342
- static instance = null;
1343
- defaultMaxAge = 5 * 60 * 1e3;
1344
- // 5 minutes
1345
- constructor() {
1346
- }
1347
- /**
1348
- * Get singleton instance
1349
- */
1350
- static getInstance() {
1351
- if (!_AgentCacheService.instance) {
1352
- _AgentCacheService.instance = new _AgentCacheService();
1353
- }
1354
- return _AgentCacheService.instance;
1355
- }
1356
115
  /**
1357
- * Check if cache is available
116
+ * Fetch transaction signatures for the facilitator address
1358
117
  */
1359
- async isCacheAvailable() {
1360
- return await isAvailable();
1361
- }
1362
- /**
1363
- * Get agent from cache
1364
- *
1365
- * @param agentAddress - Agent's Solana address
1366
- * @param options - Cache options
1367
- * @returns Agent data or null if not found/expired
1368
- */
1369
- async getAgent(agentAddress, options = {}) {
1370
- if (!await this.isCacheAvailable()) {
1371
- return null;
1372
- }
1373
- const { maxAge = this.defaultMaxAge, forceRefresh = false } = options;
1374
- if (forceRefresh) {
1375
- return null;
1376
- }
118
+ async getSignatures(before, limit) {
1377
119
  try {
1378
- const db = await getDb();
1379
- const results = await db.select().from(agents).where(eq(agents.agentAddress, agentAddress)).limit(1);
1380
- if (results.length === 0) {
1381
- return null;
1382
- }
1383
- const agent = results[0];
1384
- const age = Date.now() - agent.cachedAt;
1385
- if (age > maxAge) {
1386
- return null;
1387
- }
1388
- return agent;
120
+ const config = {
121
+ limit: limit || this.batchSize
122
+ };
123
+ if (before) {
124
+ config.before = before;
125
+ }
126
+ const response = await this.rpc.getSignaturesForAddress(this.facilitatorAddress, config).send();
127
+ return response.map((sig) => ({
128
+ signature: sig.signature,
129
+ slot: sig.slot,
130
+ blockTime: sig.blockTime,
131
+ err: sig.err ?? null
132
+ }));
1389
133
  } catch (error) {
1390
- console.warn("[AgentCacheService] Failed to get agent from cache:", error);
1391
- return null;
134
+ console.error("[X402 Indexer] Failed to fetch signatures:", error);
135
+ throw error;
1392
136
  }
1393
137
  }
1394
138
  /**
1395
- * Get multiple agents from cache
1396
- *
1397
- * @param agentAddresses - Array of agent addresses
1398
- * @param options - Cache options
1399
- * @returns Map of address to agent data
139
+ * Check if transaction is an x402 payment
140
+ *
141
+ * x402 payments are characterized by:
142
+ * - SPL token transfer (TokenProgram or Token2022Program)
143
+ * - Transfer TO the facilitator address
144
+ * - Optional memo instruction with payment metadata
1400
145
  */
1401
- async getAgents(agentAddresses, options = {}) {
1402
- if (!await this.isCacheAvailable() || agentAddresses.length === 0) {
1403
- return /* @__PURE__ */ new Map();
1404
- }
1405
- const { maxAge = this.defaultMaxAge } = options;
146
+ isX402Payment(transaction) {
1406
147
  try {
1407
- const db = await getDb();
1408
- const results = await db.select().from(agents).where(sql`${agents.agentAddress} IN ${agentAddresses}`);
1409
- const now = Date.now();
1410
- const agentMap = /* @__PURE__ */ new Map();
1411
- for (const agent of results) {
1412
- const age = now - agent.cachedAt;
1413
- if (age <= maxAge) {
1414
- agentMap.set(agent.agentAddress, agent);
148
+ const instructions = transaction.transaction?.message?.instructions || [];
149
+ const hasTokenTransfer = instructions.some((ix) => {
150
+ const programId = ix.programId?.toString();
151
+ const isTokenProgram = programId === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" || // SPL Token
152
+ programId === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
153
+ if (!isTokenProgram) return false;
154
+ const parsed = ix.parsed;
155
+ if (parsed?.type === "transfer" || parsed?.type === "transferChecked") {
156
+ const destination = parsed.info?.destination;
157
+ return destination === this.facilitatorAddress.toString();
1415
158
  }
1416
- }
1417
- return agentMap;
159
+ return false;
160
+ });
161
+ return hasTokenTransfer;
1418
162
  } catch (error) {
1419
- console.warn("[AgentCacheService] Failed to get agents from cache:", error);
1420
- return /* @__PURE__ */ new Map();
163
+ console.error("[X402 Indexer] Error checking if x402 payment:", error);
164
+ return false;
1421
165
  }
1422
166
  }
1423
167
  /**
1424
- * Cache agent data
1425
- *
1426
- * @param agent - Agent data to cache
1427
- * @param capabilities - Agent capabilities
1428
- * @param pricing - Agent pricing info
168
+ * Extract payment data from transaction
1429
169
  */
1430
- async cacheAgent(agent, capabilities = [], pricing = []) {
1431
- if (!await this.isCacheAvailable()) {
1432
- return;
1433
- }
170
+ extractPaymentData(transaction, signature) {
1434
171
  try {
1435
- const db = await getDb();
1436
- await db.insert(agents).values({
1437
- ...agent,
1438
- cachedAt: Date.now()
1439
- }).onConflictDoUpdate({
1440
- target: agents.agentAddress,
1441
- set: {
1442
- ...agent,
1443
- cachedAt: Date.now(),
1444
- updatedAt: Date.now()
1445
- }
172
+ const instructions = transaction.transaction?.message?.instructions || [];
173
+ const transferIx = instructions.find((ix) => {
174
+ const parsed = ix.parsed;
175
+ return parsed?.type === "transfer" || parsed?.type === "transferChecked";
1446
176
  });
1447
- await db.delete(agentCapabilities).where(eq(agentCapabilities.agentAddress, agent.agentAddress));
1448
- if (capabilities.length > 0) {
1449
- await db.insert(agentCapabilities).values(
1450
- capabilities.map((cap) => ({
1451
- agentAddress: agent.agentAddress,
1452
- capability: cap
1453
- }))
1454
- );
177
+ if (!transferIx) {
178
+ return null;
1455
179
  }
1456
- await db.delete(agentPricing).where(eq(agentPricing.agentAddress, agent.agentAddress));
1457
- if (pricing.length > 0) {
1458
- await db.insert(agentPricing).values(
1459
- pricing.map((p) => ({
1460
- agentAddress: agent.agentAddress,
1461
- ...p
1462
- }))
1463
- );
1464
- }
1465
- } catch (error) {
1466
- console.error("[AgentCacheService] Failed to cache agent:", error);
1467
- }
1468
- }
1469
- /**
1470
- * List agents with filters
1471
- *
1472
- * @param filters - Query filters
1473
- * @returns Array of agents
1474
- */
1475
- async listAgents(filters = {}) {
1476
- if (!await this.isCacheAvailable()) {
1477
- return [];
1478
- }
1479
- try {
1480
- const db = await getDb();
1481
- const {
1482
- x402Enabled,
1483
- framework,
1484
- isVerified,
1485
- minReputation,
1486
- limit = 50,
1487
- offset = 0
1488
- } = filters;
1489
- const conditions = [];
1490
- if (x402Enabled !== void 0) {
1491
- conditions.push(eq(agents.x402Enabled, x402Enabled));
1492
- }
1493
- if (framework) {
1494
- conditions.push(eq(agents.frameworkOrigin, framework));
1495
- }
1496
- if (isVerified !== void 0) {
1497
- conditions.push(eq(agents.isVerified, isVerified));
1498
- }
1499
- if (minReputation !== void 0) {
1500
- conditions.push(sql`${agents.reputationScore} >= ${minReputation}`);
1501
- }
1502
- if (conditions.length > 0) {
1503
- const results = await db.select().from(agents).where(and(...conditions)).orderBy(desc(agents.reputationScore)).limit(limit).offset(offset);
1504
- return results;
1505
- } else {
1506
- const results = await db.select().from(agents).orderBy(desc(agents.reputationScore)).limit(limit).offset(offset);
1507
- return results;
1508
- }
1509
- } catch (error) {
1510
- console.warn("[AgentCacheService] Failed to list agents:", error);
1511
- return [];
1512
- }
1513
- }
1514
- /**
1515
- * Invalidate cached agent
1516
- *
1517
- * @param agentAddress - Agent address to invalidate
1518
- */
1519
- async invalidateAgent(agentAddress) {
1520
- if (!await this.isCacheAvailable()) {
1521
- return;
1522
- }
1523
- try {
1524
- const db = await getDb();
1525
- await db.delete(agents).where(eq(agents.agentAddress, agentAddress));
1526
- } catch (error) {
1527
- console.warn("[AgentCacheService] Failed to invalidate agent:", error);
1528
- }
1529
- }
1530
- /**
1531
- * Clear all cached agents
1532
- */
1533
- async clearCache() {
1534
- if (!await this.isCacheAvailable()) {
1535
- return;
1536
- }
1537
- try {
1538
- const db = await getDb();
1539
- await db.delete(agents);
1540
- } catch (error) {
1541
- console.error("[AgentCacheService] Failed to clear cache:", error);
1542
- }
1543
- }
1544
- /**
1545
- * Get cache statistics
1546
- */
1547
- async getCacheStats() {
1548
- if (!await this.isCacheAvailable()) {
1549
- return null;
1550
- }
1551
- try {
1552
- const db = await getDb();
1553
- const result = await db.select({
1554
- count: sql`count(*)`,
1555
- avgAge: sql`avg(${Date.now()} - ${agents.cachedAt})`,
1556
- oldestCache: sql`min(${agents.cachedAt})`
1557
- }).from(agents);
1558
- return {
1559
- totalAgents: result[0].count,
1560
- averageAge: result[0].avgAge,
1561
- oldestCache: result[0].oldestCache
1562
- };
1563
- } catch (error) {
1564
- console.warn("[AgentCacheService] Failed to get cache stats:", error);
1565
- return null;
1566
- }
1567
- }
1568
- };
1569
- AgentCacheService.getInstance();
1570
-
1571
- // src/x402/AgentDiscoveryClient.ts
1572
- var REPUTATION_BASIS_POINTS_PER_STAR = 2e3;
1573
- var AgentDiscoveryClient = class {
1574
- rpc;
1575
- programId;
1576
- commitment;
1577
- cache = /* @__PURE__ */ new Map();
1578
- cacheEnabled;
1579
- cacheTTL;
1580
- useDatabaseCache;
1581
- dbCache;
1582
- constructor(options) {
1583
- this.rpc = createSolanaRpc(options.rpcEndpoint);
1584
- this.programId = options.programId;
1585
- this.commitment = options.commitment ?? "confirmed";
1586
- this.cacheEnabled = options.cacheEnabled ?? true;
1587
- this.cacheTTL = options.cacheTTL ?? 300;
1588
- this.useDatabaseCache = options.useDatabaseCache ?? true;
1589
- this.dbCache = AgentCacheService.getInstance();
1590
- }
1591
- /**
1592
- * Search for agents with filters
1593
- */
1594
- async searchAgents(params = {}) {
1595
- const cacheKey = this.getCacheKey("search", params);
1596
- if (this.cacheEnabled) {
1597
- const cached = this.getFromCache(cacheKey);
1598
- if (cached) return cached;
1599
- }
1600
- const page = params.page ?? 1;
1601
- const limit = Math.min(params.limit ?? 20, 100);
1602
- const sortBy = params.sort_by ?? "reputation";
1603
- const sortOrder = params.sort_order ?? "desc";
1604
- const allAgents = await this.fetchAgentsFromChain(params);
1605
- let filteredAgents = this.applyFilters(allAgents, params);
1606
- filteredAgents = this.sortAgents(filteredAgents, sortBy, sortOrder);
1607
- const total = filteredAgents.length;
1608
- const totalPages = Math.ceil(total / limit);
1609
- const startIndex = (page - 1) * limit;
1610
- const endIndex = startIndex + limit;
1611
- const paginatedAgents = filteredAgents.slice(startIndex, endIndex);
1612
- const response = {
1613
- agents: paginatedAgents,
1614
- pagination: {
1615
- page,
1616
- limit,
1617
- total,
1618
- totalPages
1619
- },
1620
- filters: params
1621
- };
1622
- if (this.cacheEnabled) {
1623
- this.setCache(cacheKey, response);
1624
- }
1625
- return response;
1626
- }
1627
- /**
1628
- * Get agent by address with database cache support
1629
- *
1630
- * Cache hierarchy:
1631
- * 1. Check Turso database cache (if enabled)
1632
- * 2. Fallback to RPC fetch
1633
- * 3. Cache result in database for future requests
1634
- */
1635
- async getAgent(address6, forceRefresh = false) {
1636
- const cacheKey = this.getCacheKey("agent", { address: address6 });
1637
- if (this.useDatabaseCache && !forceRefresh) {
1638
- const cachedAgent = await this.dbCache.getAgent(address6, {
1639
- maxAge: this.cacheTTL * 1e3,
1640
- forceRefresh
1641
- });
1642
- if (cachedAgent) {
1643
- console.log(`[AgentDiscovery] Cache HIT for agent ${address6}`);
1644
- return this.transformCachedAgent(cachedAgent);
1645
- }
1646
- }
1647
- if (this.cacheEnabled && !forceRefresh) {
1648
- const cached = this.getFromCache(cacheKey);
1649
- if (cached) {
1650
- console.log(`[AgentDiscovery] Memory cache HIT for agent ${address6}`);
1651
- return cached;
1652
- }
1653
- }
1654
- console.log(`[AgentDiscovery] Cache MISS for agent ${address6}, fetching from RPC`);
1655
- try {
1656
- const result = await this.rpc.getAccountInfo(address6, {
1657
- commitment: this.commitment,
1658
- encoding: "base64"
1659
- }).send();
1660
- const accountInfo = result;
1661
- if (!accountInfo.value) return null;
1662
- const agent = this.parseAgentAccount(address6, accountInfo.value.data);
1663
- if (agent) {
1664
- if (this.useDatabaseCache) {
1665
- this.cacheAgentInDatabase(agent).catch(
1666
- (err) => console.warn("[AgentDiscovery] Failed to cache agent in database:", err)
1667
- );
1668
- }
1669
- if (this.cacheEnabled) {
1670
- this.setCache(cacheKey, agent);
1671
- }
1672
- }
1673
- return agent;
1674
- } catch (error) {
1675
- console.error(`Failed to fetch agent ${address6}:`, error);
1676
- return null;
1677
- }
1678
- }
1679
- /**
1680
- * Helper to cache agent in database
1681
- */
1682
- async cacheAgentInDatabase(agent) {
1683
- await this.dbCache.cacheAgent(
1684
- {
1685
- agentAddress: agent.address,
1686
- owner: agent.owner,
1687
- name: agent.name,
1688
- description: agent.description,
1689
- reputationScore: agent.reputation_score,
1690
- totalJobsCompleted: Number(agent.total_jobs),
1691
- totalEarnings: agent.total_earnings.toString(),
1692
- x402Enabled: agent.x402_enabled,
1693
- x402PaymentAddress: agent.x402_payment_address,
1694
- x402PricePerCall: agent.x402_price_per_call.toString(),
1695
- x402ServiceEndpoint: agent.x402_service_endpoint,
1696
- x402TotalPayments: agent.x402_total_payments.toString(),
1697
- x402TotalCalls: agent.x402_total_calls.toString(),
1698
- lastPaymentTimestamp: Number(agent.last_payment_timestamp),
1699
- metadataUri: agent.metadata_uri,
1700
- frameworkOrigin: agent.framework_origin,
1701
- isVerified: agent.is_verified,
1702
- createdAt: Number(agent.created_at),
1703
- updatedAt: Date.now(),
1704
- cachedAt: Date.now(),
1705
- bump: 0
1706
- // Placeholder
1707
- },
1708
- agent.capabilities,
1709
- []
1710
- // Pricing info would be added here
1711
- );
1712
- }
1713
- /**
1714
- * Transform cached database agent to Agent interface
1715
- */
1716
- transformCachedAgent(cachedAgent) {
1717
- return {
1718
- address: cachedAgent.agentAddress,
1719
- owner: cachedAgent.owner,
1720
- name: cachedAgent.name,
1721
- description: cachedAgent.description,
1722
- capabilities: [],
1723
- // Would need to join from agentCapabilities table
1724
- x402_enabled: Boolean(cachedAgent.x402Enabled),
1725
- x402_payment_address: cachedAgent.x402PaymentAddress,
1726
- x402_accepted_tokens: [],
1727
- // Would join from agentPricing table
1728
- x402_price_per_call: BigInt(cachedAgent.x402PricePerCall),
1729
- x402_service_endpoint: cachedAgent.x402ServiceEndpoint,
1730
- x402_total_payments: BigInt(cachedAgent.x402TotalPayments),
1731
- x402_total_calls: BigInt(cachedAgent.x402TotalCalls),
1732
- last_payment_timestamp: BigInt(cachedAgent.lastPaymentTimestamp),
1733
- reputation_score: cachedAgent.reputationScore,
1734
- total_jobs: BigInt(cachedAgent.totalJobsCompleted),
1735
- successful_jobs: BigInt(cachedAgent.totalJobsCompleted),
1736
- total_earnings: BigInt(cachedAgent.totalEarnings),
1737
- average_rating: cachedAgent.reputationScore / REPUTATION_BASIS_POINTS_PER_STAR,
1738
- created_at: BigInt(cachedAgent.createdAt),
1739
- metadata_uri: cachedAgent.metadataUri,
1740
- framework_origin: cachedAgent.frameworkOrigin,
1741
- is_verified: Boolean(cachedAgent.isVerified)
1742
- };
1743
- }
1744
- /**
1745
- * Get agent pricing information
1746
- */
1747
- async getAgentPricing(address6) {
1748
- const agent = await this.getAgent(address6);
1749
- if (!agent?.x402_enabled) return null;
1750
- return {
1751
- price_per_call: agent.x402_price_per_call,
1752
- accepted_tokens: await this.getTokenInfo(agent.x402_accepted_tokens),
1753
- payment_address: agent.x402_payment_address,
1754
- service_endpoint: agent.x402_service_endpoint
1755
- };
1756
- }
1757
- /**
1758
- * Get recommended agents based on criteria
1759
- */
1760
- async getRecommendedAgents(capability, limit = 10) {
1761
- const params = {
1762
- capability,
1763
- x402_enabled: true,
1764
- sort_by: "reputation",
1765
- sort_order: "desc",
1766
- limit,
1767
- min_reputation: 7e3
1768
- // Only recommend highly rated agents (7.0+)
1769
- };
1770
- const response = await this.searchAgents(params);
1771
- return response.agents;
1772
- }
1773
- /**
1774
- * Get agents by capability
1775
- */
1776
- async getAgentsByCapability(capability) {
1777
- const response = await this.searchAgents({
1778
- capability,
1779
- x402_enabled: true
1780
- });
1781
- return response.agents;
1782
- }
1783
- /**
1784
- * Get agents accepting specific token
1785
- */
1786
- async getAgentsByToken(tokenAddress) {
1787
- const response = await this.searchAgents({
1788
- accepted_tokens: [tokenAddress],
1789
- x402_enabled: true
1790
- });
1791
- return response.agents;
1792
- }
1793
- /**
1794
- * Get agents within price range
1795
- */
1796
- async getAgentsByPriceRange(maxPrice, capability) {
1797
- const response = await this.searchAgents({
1798
- max_price: maxPrice,
1799
- capability,
1800
- x402_enabled: true,
1801
- sort_by: "price",
1802
- sort_order: "asc"
1803
- });
1804
- return response.agents;
1805
- }
1806
- /**
1807
- * Search agents by text query
1808
- */
1809
- async searchByQuery(query) {
1810
- const response = await this.searchAgents({
1811
- query,
1812
- x402_enabled: true
1813
- });
1814
- return response.agents;
1815
- }
1816
- // Private helper methods
1817
- async fetchAgentsFromChain(params) {
1818
- try {
1819
- const filters = [];
1820
- filters.push({ dataSize: 359n });
1821
- const accounts = await this.rpc.getProgramAccounts(this.programId, {
1822
- commitment: this.commitment,
1823
- encoding: "base64",
1824
- filters
1825
- }).send();
1826
- const agents2 = [];
1827
- for (const { pubkey, account } of accounts) {
1828
- const agent = this.parseAgentAccount(pubkey, account.data);
1829
- if (agent) {
1830
- agents2.push(agent);
1831
- }
1832
- }
1833
- return agents2;
1834
- } catch (error) {
1835
- console.error("Failed to fetch agents from chain:", error);
1836
- return [];
1837
- }
1838
- }
1839
- parseAgentAccount(address6, data) {
1840
- try {
1841
- let dataBytes;
1842
- if (typeof data === "string") {
1843
- dataBytes = Uint8Array.from(Buffer.from(data, "base64"));
1844
- } else if (Array.isArray(data)) {
1845
- if (data.length === 2 && typeof data[0] === "string" && typeof data[1] === "string" && data[1] === "base64") {
1846
- dataBytes = Uint8Array.from(Buffer.from(data[0], "base64"));
1847
- } else {
1848
- dataBytes = Uint8Array.from(data);
1849
- }
1850
- } else if (data instanceof Uint8Array) {
1851
- dataBytes = data;
1852
- } else {
1853
- throw new Error("Invalid data format");
1854
- }
1855
- const decoder = getAgentDecoder();
1856
- const decodedData = decoder.decode(dataBytes);
1857
- const decodedAgent = Array.isArray(decodedData) ? decodedData[0] : decodedData;
1858
- return {
1859
- address: address6,
1860
- owner: decodedAgent.owner,
1861
- name: decodedAgent.name,
1862
- description: decodedAgent.description,
1863
- capabilities: decodedAgent.capabilities,
1864
- // x402 fields
1865
- x402_enabled: decodedAgent.x402Enabled,
1866
- x402_payment_address: decodedAgent.x402PaymentAddress,
1867
- x402_accepted_tokens: decodedAgent.x402AcceptedTokens,
1868
- x402_price_per_call: decodedAgent.x402PricePerCall,
1869
- x402_service_endpoint: decodedAgent.x402ServiceEndpoint,
1870
- x402_total_payments: decodedAgent.x402TotalPayments,
1871
- x402_total_calls: decodedAgent.x402TotalCalls,
1872
- last_payment_timestamp: decodedAgent.lastPaymentTimestamp,
1873
- // Standard fields
1874
- reputation_score: decodedAgent.reputationScore,
1875
- total_jobs: BigInt(decodedAgent.totalJobsCompleted),
1876
- successful_jobs: BigInt(decodedAgent.totalJobsCompleted),
1877
- // Assuming successful = completed
1878
- total_earnings: decodedAgent.totalEarnings,
1879
- average_rating: decodedAgent.reputationScore / REPUTATION_BASIS_POINTS_PER_STAR,
1880
- // Convert from basis points to 1-5 scale
1881
- created_at: decodedAgent.createdAt,
1882
- metadata_uri: decodedAgent.metadataUri,
1883
- framework_origin: decodedAgent.frameworkOrigin,
1884
- is_verified: decodedAgent.isVerified
1885
- };
1886
- } catch (error) {
1887
- console.error("Failed to parse agent account:", error);
1888
- return null;
1889
- }
1890
- }
1891
- applyFilters(agents2, params) {
1892
- let filtered = agents2;
1893
- if (params.x402_enabled !== void 0) {
1894
- filtered = filtered.filter((a) => a.x402_enabled === params.x402_enabled);
1895
- }
1896
- if (params.capability) {
1897
- filtered = filtered.filter(
1898
- (a) => a.capabilities.some(
1899
- (c) => c.toLowerCase().includes(params.capability.toLowerCase())
1900
- )
1901
- );
1902
- }
1903
- if (params.accepted_tokens?.length) {
1904
- filtered = filtered.filter(
1905
- (a) => params.accepted_tokens.some(
1906
- (token) => a.x402_accepted_tokens.includes(token)
1907
- )
1908
- );
1909
- }
1910
- if (params.min_reputation !== void 0) {
1911
- filtered = filtered.filter((a) => a.reputation_score >= params.min_reputation);
1912
- }
1913
- if (params.max_price !== void 0) {
1914
- filtered = filtered.filter((a) => a.x402_price_per_call <= params.max_price);
1915
- }
1916
- if (params.framework_origin) {
1917
- filtered = filtered.filter(
1918
- (a) => a.framework_origin.toLowerCase() === params.framework_origin.toLowerCase()
180
+ const transferInfo = transferIx.parsed.info;
181
+ const merchant = transferInfo.destination;
182
+ const payer = transferInfo.source;
183
+ const amount = transferInfo.amount || transferInfo.tokenAmount?.amount || "0";
184
+ const success = transaction.meta?.err === null;
185
+ const blockTime = transaction.blockTime;
186
+ const timestamp = blockTime ? new Date(blockTime * 1e3) : /* @__PURE__ */ new Date();
187
+ const memoIx = instructions.find(
188
+ (ix) => ix.programId?.toString()?.includes("Memo")
1919
189
  );
1920
- }
1921
- if (params.is_verified !== void 0) {
1922
- filtered = filtered.filter((a) => a.is_verified === params.is_verified);
1923
- }
1924
- if (params.query) {
1925
- const query = params.query.toLowerCase();
1926
- filtered = filtered.filter(
1927
- (a) => a.name.toLowerCase().includes(query) || a.description.toLowerCase().includes(query)
1928
- );
1929
- }
1930
- return filtered;
1931
- }
1932
- sortAgents(agents2, sortBy, sortOrder) {
1933
- const sorted = [...agents2];
1934
- const order = sortOrder === "asc" ? 1 : -1;
1935
- sorted.sort((a, b) => {
1936
- let comparison = 0;
1937
- switch (sortBy) {
1938
- case "reputation":
1939
- comparison = a.reputation_score - b.reputation_score;
1940
- break;
1941
- case "price":
1942
- comparison = Number(a.x402_price_per_call - b.x402_price_per_call);
1943
- break;
1944
- case "total_jobs":
1945
- comparison = Number(a.total_jobs - b.total_jobs);
1946
- break;
1947
- case "created_at":
1948
- comparison = Number(a.created_at - b.created_at);
1949
- break;
1950
- }
1951
- return comparison * order;
1952
- });
1953
- return sorted;
1954
- }
1955
- async getTokenInfo(tokens) {
1956
- const tokenInfo = [];
1957
- for (const token of tokens) {
1958
- try {
1959
- const result = await this.rpc.getAccountInfo(token, {
1960
- commitment: this.commitment,
1961
- encoding: "base64"
1962
- }).send();
1963
- const mintInfo = result;
1964
- if (mintInfo.value) {
1965
- const data = Buffer.from(mintInfo.value.data[0], "base64");
1966
- const decimals = data[44];
1967
- tokenInfo.push({
1968
- token,
1969
- decimals,
1970
- symbol: "USDC"
1971
- // Placeholder - would look up from token registry or metadata
1972
- });
1973
- }
1974
- } catch (error) {
1975
- console.error(`Failed to fetch token info for ${token}:`, error);
1976
- }
1977
- }
1978
- return tokenInfo;
1979
- }
1980
- getCacheKey(prefix, params) {
1981
- return `${prefix}:${JSON.stringify(params)}`;
1982
- }
1983
- getFromCache(key) {
1984
- const cached = this.cache.get(key);
1985
- if (!cached) return null;
1986
- if (Date.now() > cached.expiry) {
1987
- this.cache.delete(key);
1988
- return null;
1989
- }
1990
- return cached.data;
1991
- }
1992
- setCache(key, data) {
1993
- const expiry = Date.now() + this.cacheTTL * 1e3;
1994
- this.cache.set(key, { data, expiry });
1995
- if (this.cache.size > 1e3) {
1996
- const entries = Array.from(this.cache.entries());
1997
- entries.sort((a, b) => a[1].expiry - b[1].expiry);
1998
- for (let i = 0; i < 100; i++) {
1999
- this.cache.delete(entries[i][0]);
2000
- }
2001
- }
2002
- }
2003
- /**
2004
- * Clear all cached data
2005
- */
2006
- clearCache() {
2007
- this.cache.clear();
2008
- }
2009
- /**
2010
- * Get cache statistics
2011
- */
2012
- getCacheStats() {
2013
- return {
2014
- size: this.cache.size,
2015
- enabled: this.cacheEnabled,
2016
- ttl: this.cacheTTL
2017
- };
2018
- }
2019
- };
2020
- function createAgentDiscoveryClient(options) {
2021
- return new AgentDiscoveryClient(options);
2022
- }
2023
- function toSignature(value) {
2024
- if (typeof value === "string") {
2025
- return value;
2026
- }
2027
- return value;
2028
- }
2029
- var SignatureCache = class {
2030
- cache = /* @__PURE__ */ new Map();
2031
- ttl;
2032
- cleanupInterval = null;
2033
- constructor(ttl = 3600) {
2034
- this.ttl = ttl * 1e3;
2035
- this.cleanupInterval = setInterval(() => this.cleanup(), 3e5);
2036
- if (this.cleanupInterval.unref) {
2037
- this.cleanupInterval.unref();
2038
- }
2039
- }
2040
- has(signature) {
2041
- const entry = this.cache.get(signature);
2042
- if (!entry) return false;
2043
- if (Date.now() > entry.expiresAt) {
2044
- this.cache.delete(signature);
2045
- return false;
2046
- }
2047
- return true;
2048
- }
2049
- add(signature) {
2050
- this.cache.set(signature, {
2051
- timestamp: Date.now(),
2052
- expiresAt: Date.now() + this.ttl
2053
- });
2054
- }
2055
- cleanup() {
2056
- const now = Date.now();
2057
- for (const [signature, entry] of this.cache.entries()) {
2058
- if (now > entry.expiresAt) {
2059
- this.cache.delete(signature);
2060
- }
2061
- }
2062
- }
2063
- getSize() {
2064
- return this.cache.size;
2065
- }
2066
- /**
2067
- * Destroy the cache and clear the cleanup interval
2068
- * Call this when shutting down to prevent memory leaks
2069
- */
2070
- destroy() {
2071
- if (this.cleanupInterval) {
2072
- clearInterval(this.cleanupInterval);
2073
- this.cleanupInterval = null;
2074
- }
2075
- this.cache.clear();
2076
- }
2077
- };
2078
- var globalSignatureCache = null;
2079
- function createX402Middleware(options) {
2080
- const preventDuplicates = options.preventDuplicatePayments ?? true;
2081
- const enforceExpiration = options.enforceExpiration ?? true;
2082
- const cacheTTL = options.signatureCacheTTL ?? 3600;
2083
- const signatureCache = preventDuplicates ? options.signatureCacheTTL ? new SignatureCache(cacheTTL) : globalSignatureCache : null;
2084
- return async (req, res, next) => {
2085
- const requestStartTime = Date.now();
2086
- const paymentSignature = req.headers["x-payment-signature"];
2087
- const paymentExpiresAt = req.headers["x-payment-expires-at"];
2088
- if (options.allowBypass && shouldBypass(req, options)) {
2089
- return next();
2090
- }
2091
- const paymentRequest = options.x402Client.createPaymentRequest({
2092
- amount: options.requiredPayment,
2093
- token: options.token,
2094
- description: options.description
2095
- });
2096
- if (!paymentSignature) {
2097
- const headers = options.x402Client.createPaymentHeaders(paymentRequest);
2098
- res.status(402).set(headers).json({
2099
- error: "Payment Required",
2100
- message: "This endpoint requires x402 payment",
2101
- code: "PAYMENT_REQUIRED",
2102
- paymentDetails: {
2103
- address: paymentRequest.recipient,
2104
- amount: paymentRequest.amount.toString(),
2105
- token: paymentRequest.token,
2106
- blockchain: "solana",
2107
- description: options.description,
2108
- expiresAt: paymentRequest.expiresAt
2109
- },
2110
- documentation: "https://docs.ghostspeak.ai/x402"
2111
- });
2112
- return;
2113
- }
2114
- if (preventDuplicates && signatureCache?.has(paymentSignature)) {
2115
- if (options.onPaymentFailed) {
2116
- await options.onPaymentFailed("Payment signature already used", req);
2117
- }
2118
- res.status(402).json({
2119
- error: "Payment Already Used",
2120
- message: "This payment signature has already been used. Please create a new payment.",
2121
- code: "PAYMENT_DUPLICATE"
2122
- });
2123
- return;
2124
- }
2125
- if (enforceExpiration && paymentExpiresAt) {
2126
- const now = Date.now();
2127
- const expiresAtTimestamp = parseInt(paymentExpiresAt, 10);
2128
- if (isNaN(expiresAtTimestamp)) {
2129
- if (options.onPaymentFailed) {
2130
- await options.onPaymentFailed("Invalid expiration timestamp", req);
2131
- }
2132
- res.status(402).json({
2133
- error: "Invalid Payment Expiration",
2134
- message: "The x-payment-expires-at header contains an invalid timestamp.",
2135
- code: "PAYMENT_INVALID_EXPIRY"
2136
- });
2137
- return;
2138
- }
2139
- if (now > expiresAtTimestamp) {
2140
- if (options.onPaymentFailed) {
2141
- await options.onPaymentFailed("Payment request expired", req);
2142
- }
2143
- res.status(402).json({
2144
- error: "Payment Expired",
2145
- message: "This payment request has expired. Please create a new payment.",
2146
- code: "PAYMENT_EXPIRED",
2147
- expiresAt: expiresAtTimestamp,
2148
- currentTime: now
2149
- });
2150
- return;
2151
- }
2152
- }
2153
- try {
2154
- const verification = await options.x402Client.verifyPaymentDetails({
2155
- signature: toSignature(paymentSignature),
2156
- expectedRecipient: paymentRequest.recipient,
2157
- expectedAmount: options.requiredPayment,
2158
- expectedToken: options.token
2159
- });
2160
- if (!verification.valid) {
2161
- if (options.onPaymentFailed) {
2162
- await options.onPaymentFailed(verification.error ?? "Unknown error", req);
2163
- }
2164
- res.status(402).json({
2165
- error: "Payment Verification Failed",
2166
- message: verification.error ?? "Invalid payment",
2167
- code: "PAYMENT_INVALID"
2168
- });
2169
- return;
2170
- }
2171
- const responseTimeMs = Date.now() - requestStartTime;
2172
- let callerIdentity;
2173
- if (options.lookupCallerIdentity) {
190
+ let responseTimeMs;
191
+ let metadata;
192
+ if (memoIx && memoIx.data) {
2174
193
  try {
2175
- callerIdentity = await lookupCallerIdentity(
2176
- verification.receipt.recipient,
2177
- options.rpcEndpoint,
2178
- options.programId
2179
- );
2180
- } catch (identityError) {
2181
- console.warn("[x402] Failed to lookup caller identity:", identityError);
194
+ const memoText = Buffer.from(memoIx.data, "base64").toString("utf-8");
195
+ const memoData = JSON.parse(memoText);
196
+ responseTimeMs = memoData.responseTimeMs;
197
+ metadata = memoData;
198
+ } catch {
2182
199
  }
2183
200
  }
2184
- req.x402Payment = {
2185
- signature: paymentSignature,
2186
- verified: true,
2187
- amount: verification.receipt.amount,
2188
- token: verification.receipt.token,
2189
- responseTimeMs,
2190
- timestamp: Date.now(),
2191
- caller: callerIdentity
2192
- };
2193
- if (preventDuplicates && signatureCache) {
2194
- signatureCache.add(paymentSignature);
2195
- }
2196
- if (options.recordPaymentOnChain && options.agentId) {
2197
- try {
2198
- console.log(`[x402] Would record payment on-chain for agent ${options.agentId}`);
2199
- } catch (reputationError) {
2200
- if (options.onReputationUpdateFailed && reputationError instanceof Error) {
2201
- options.onReputationUpdateFailed(reputationError);
2202
- } else {
2203
- console.error("[x402] Failed to record payment on-chain:", reputationError);
2204
- }
2205
- }
2206
- }
2207
- if (options.onPaymentVerified) {
2208
- await options.onPaymentVerified(paymentSignature, req);
2209
- }
2210
- next();
2211
- } catch (error) {
2212
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
2213
- if (options.onPaymentFailed) {
2214
- await options.onPaymentFailed(errorMessage, req);
2215
- }
2216
- res.status(500).json({
2217
- error: "Payment Verification Error",
2218
- message: errorMessage,
2219
- code: "PAYMENT_VERIFICATION_ERROR"
2220
- });
2221
- }
2222
- };
2223
- }
2224
- function x402FastifyPlugin(fastify, options) {
2225
- fastify.addHook("preHandler", async (request, reply) => {
2226
- const route = request.url ? options.routes[request.url] : void 0;
2227
- if (!route) {
2228
- return;
2229
- }
2230
- const paymentSignature = request.headers["x-payment-signature"];
2231
- const paymentRequest = options.x402Client.createPaymentRequest({
2232
- amount: route.payment,
2233
- token: route.token,
2234
- description: route.description
2235
- });
2236
- if (!paymentSignature) {
2237
- const headers = options.x402Client.createPaymentHeaders(paymentRequest);
2238
- reply.code(402).headers(headers).send({
2239
- error: "Payment Required",
2240
- paymentDetails: {
2241
- address: paymentRequest.recipient,
2242
- amount: paymentRequest.amount.toString(),
2243
- token: paymentRequest.token
2244
- }
2245
- });
2246
- return;
2247
- }
2248
- const verification = await options.x402Client.verifyPaymentDetails({
2249
- signature: toSignature(paymentSignature),
2250
- expectedRecipient: paymentRequest.recipient,
2251
- expectedAmount: route.payment,
2252
- expectedToken: route.token
2253
- });
2254
- if (!verification.valid) {
2255
- reply.code(402).send({
2256
- error: "Payment Verification Failed",
2257
- message: verification.error
2258
- });
2259
- return;
2260
- }
2261
- request.x402Payment = {
2262
- signature: paymentSignature,
2263
- verified: true,
2264
- amount: verification.receipt.amount,
2265
- token: verification.receipt.token
2266
- };
2267
- });
2268
- }
2269
- function shouldBypass(req, options) {
2270
- const clientAddress = req.headers["x-client-address"];
2271
- if (clientAddress && options.bypassAddresses) {
2272
- return options.bypassAddresses.includes(clientAddress);
2273
- }
2274
- return false;
2275
- }
2276
- async function lookupCallerIdentity(sourceAddress, rpcEndpoint, programId) {
2277
- if (!rpcEndpoint) {
2278
- return {
2279
- type: "unknown",
2280
- address: sourceAddress
2281
- };
2282
- }
2283
- try {
2284
- const rpc = createSolanaRpc(rpcEndpoint);
2285
- const maybeAgent = await fetchMaybeAgent(rpc, sourceAddress);
2286
- if (!maybeAgent.exists) {
2287
201
  return {
2288
- type: "unknown",
2289
- address: sourceAddress
2290
- };
2291
- }
2292
- const agent = maybeAgent.data;
2293
- return {
2294
- type: "agent",
2295
- address: sourceAddress,
2296
- agent: {
2297
- name: agent.name,
2298
- owner: agent.owner,
2299
- reputation_score: agent.reputationScore,
2300
- is_verified: agent.isVerified,
2301
- capabilities: agent.capabilities,
2302
- framework_origin: agent.frameworkOrigin,
2303
- x402_enabled: true
2304
- // Assume all agents support x402 (no explicit flag in schema)
2305
- }
2306
- };
2307
- } catch (error) {
2308
- console.warn("[x402] Agent lookup failed:", error);
2309
- return {
2310
- type: "unknown",
2311
- address: sourceAddress
2312
- };
2313
- }
2314
- }
2315
- function withX402RateLimit(options) {
2316
- const requests = /* @__PURE__ */ new Map();
2317
- return (target, propertyKey, descriptor) => {
2318
- const originalMethod = descriptor.value;
2319
- descriptor.value = async function(...args) {
2320
- const req = args[0];
2321
- const res = args[1];
2322
- const forwardedFor = req.headers["x-forwarded-for"];
2323
- const clientIp = forwardedFor?.split(",")[0]?.trim() ?? req.ip ?? "unknown";
2324
- const clientId = req.x402Payment?.signature ?? clientIp;
2325
- const now = Date.now();
2326
- const userRequests = requests.get(clientId) ?? [];
2327
- const recentRequests = userRequests.filter(
2328
- (timestamp) => now - timestamp < 6e4
2329
- );
2330
- if (recentRequests.length >= options.maxRequestsPerMinute) {
2331
- res.status(429).json({
2332
- error: "Rate Limit Exceeded",
2333
- message: `Maximum ${options.maxRequestsPerMinute} requests per minute`,
2334
- paymentRequired: options.paymentRequired.toString()
2335
- });
2336
- return;
2337
- }
2338
- recentRequests.push(now);
2339
- requests.set(clientId, recentRequests);
2340
- return originalMethod.apply(this, args);
2341
- };
2342
- };
2343
- }
2344
-
2345
- // src/x402/schemas/enhanced-x402.ts
2346
- function validatePaymentRequirement(req) {
2347
- const errors = [];
2348
- const r = req;
2349
- if (!r || typeof r !== "object") {
2350
- return { valid: false, errors: ["Payment requirement must be an object"] };
2351
- }
2352
- if (!r.network || typeof r.network !== "string") {
2353
- errors.push('Missing or invalid "network" field');
2354
- }
2355
- if (!r.maxAmountRequired && !r.max_amount_required && !r.amount) {
2356
- errors.push('Missing "maxAmountRequired" field');
2357
- }
2358
- if (!r.payTo && !r.pay_to && !r.recipient) {
2359
- errors.push('Missing "payTo" field');
2360
- }
2361
- if (!r.asset && !r.token) {
2362
- errors.push('Missing "asset" field');
2363
- }
2364
- if (errors.length > 0) {
2365
- return { valid: false, errors };
2366
- }
2367
- const requirement = {
2368
- scheme: r.scheme ?? "exact",
2369
- network: r.network ?? r.chain,
2370
- maxAmountRequired: String(r.maxAmountRequired ?? r.max_amount_required ?? r.amount),
2371
- resource: r.resource,
2372
- description: r.description,
2373
- mimeType: r.mimeType ?? r.mime_type,
2374
- payTo: String(r.payTo ?? r.pay_to ?? r.recipient),
2375
- maxTimeoutSeconds: r.maxTimeoutSeconds ?? r.max_timeout_seconds,
2376
- asset: String(r.asset ?? r.token),
2377
- extra: r.extra
2378
- };
2379
- return { valid: true, requirement };
2380
- }
2381
- function validateX402Response(response) {
2382
- const errors = [];
2383
- const r = response;
2384
- if (!r || typeof r !== "object") {
2385
- return { valid: false, errors: ["Response must be an object"] };
2386
- }
2387
- const version = r.x402Version ?? r.x402_version;
2388
- if (!version) {
2389
- errors.push('Missing "x402Version" field');
2390
- }
2391
- const accepts = r.accepts ?? r.payment_requirements;
2392
- if (!accepts || !Array.isArray(accepts)) {
2393
- errors.push('Missing or invalid "accepts" array');
2394
- } else if (accepts.length === 0) {
2395
- errors.push('"accepts" array must not be empty');
2396
- } else {
2397
- for (let i = 0; i < accepts.length; i++) {
2398
- const result = validatePaymentRequirement(accepts[i]);
2399
- if (!result.valid) {
2400
- errors.push(`accepts[${i}]: ${result.errors.join(", ")}`);
2401
- }
2402
- }
2403
- }
2404
- if (errors.length > 0) {
2405
- return { valid: false, errors };
2406
- }
2407
- const enhanced = {
2408
- x402Version: "1.0",
2409
- accepts: accepts.map((a) => {
2410
- const result = validatePaymentRequirement(a);
2411
- return result.valid ? result.requirement : {};
2412
- }),
2413
- error: r.error,
2414
- inputSchema: r.inputSchema ?? r.input_schema,
2415
- outputSchema: r.outputSchema ?? r.output_schema,
2416
- description: r.description,
2417
- name: r.name,
2418
- tags: r.tags,
2419
- category: r.category,
2420
- examples: r.examples,
2421
- apiVersion: r.apiVersion ?? r.api_version,
2422
- methods: r.methods,
2423
- rateLimit: r.rateLimit ?? r.rate_limit,
2424
- authRequired: r.authRequired ?? r.auth_required,
2425
- sla: r.sla,
2426
- termsUrl: r.termsUrl ?? r.terms_url,
2427
- privacyUrl: r.privacyUrl ?? r.privacy_url,
2428
- docsUrl: r.docsUrl ?? r.docs_url,
2429
- support: r.support
2430
- };
2431
- return { valid: true, response: enhanced };
2432
- }
2433
- function parseX402Response(body) {
2434
- try {
2435
- const parsed = JSON.parse(body);
2436
- return validateX402Response(parsed);
2437
- } catch (error) {
2438
- return {
2439
- valid: false,
2440
- errors: [`Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`]
2441
- };
2442
- }
2443
- }
2444
- var FetchWithPaymentClient = class extends EventEmitter {
2445
- wallet;
2446
- createPaymentHeader;
2447
- maxPayment;
2448
- preferredNetwork;
2449
- preferredToken;
2450
- timeout;
2451
- retries;
2452
- userAgent;
2453
- constructor(options) {
2454
- super();
2455
- this.wallet = options.wallet;
2456
- this.createPaymentHeader = options.createPaymentHeader;
2457
- this.maxPayment = options.maxPayment ?? BigInt("1000000000");
2458
- this.preferredNetwork = options.preferredNetwork;
2459
- this.preferredToken = options.preferredToken;
2460
- this.timeout = options.timeout ?? 3e4;
2461
- this.retries = options.retries ?? 1;
2462
- this.userAgent = options.userAgent ?? "GhostSpeak-x402-Fetch/1.0";
2463
- }
2464
- /**
2465
- * Make an x402-enabled fetch request
2466
- */
2467
- async fetch(url, options) {
2468
- const mergedOptions = {
2469
- ...options,
2470
- maxPayment: options?.maxPayment ?? this.maxPayment,
2471
- preferredNetwork: options?.preferredNetwork ?? this.preferredNetwork,
2472
- preferredToken: options?.preferredToken ?? this.preferredToken,
2473
- timeout: options?.timeout ?? this.timeout,
2474
- retries: options?.retries ?? this.retries
2475
- };
2476
- return this.fetchWithPayment(url, mergedOptions);
2477
- }
2478
- /**
2479
- * Internal fetch with payment logic
2480
- */
2481
- async fetchWithPayment(url, options) {
2482
- const headers = new Headers(options.headers);
2483
- headers.set("User-Agent", this.userAgent);
2484
- const initialResponse = await fetch(url, {
2485
- ...options,
2486
- headers,
2487
- signal: options.timeout ? AbortSignal.timeout(options.timeout) : void 0
2488
- });
2489
- if (initialResponse.status !== 402) {
2490
- return initialResponse;
2491
- }
2492
- const body = await initialResponse.text();
2493
- const parseResult = parseX402Response(body);
2494
- if (!parseResult.valid) {
2495
- const errorResponse = new Response(body, {
2496
- status: 402,
2497
- statusText: "Payment Required - Invalid x402 Response",
2498
- headers: initialResponse.headers
2499
- });
2500
- errorResponse.x402Requirements = [];
2501
- return errorResponse;
2502
- }
2503
- const x402Response = parseResult.response;
2504
- this.emit("paymentRequired", x402Response.accepts);
2505
- options.onPaymentRequired?.(x402Response.accepts);
2506
- if (options.dryRun) {
2507
- const dryRunResponse = new Response(body, {
2508
- status: 402,
2509
- statusText: "Payment Required",
2510
- headers: initialResponse.headers
2511
- });
2512
- dryRunResponse.x402Requirements = x402Response.accepts;
2513
- return dryRunResponse;
2514
- }
2515
- const selectedRequirement = this.selectPaymentRequirement(
2516
- x402Response.accepts,
2517
- options
2518
- );
2519
- if (!selectedRequirement) {
2520
- throw new X402PaymentError(
2521
- "No suitable payment option found within max payment limit",
2522
- x402Response.accepts
2523
- );
2524
- }
2525
- const amount = BigInt(selectedRequirement.maxAmountRequired);
2526
- if (amount > (options.maxPayment ?? this.maxPayment)) {
2527
- throw new X402PaymentError(
2528
- `Payment amount ${amount} exceeds max payment ${options.maxPayment ?? this.maxPayment}`,
2529
- x402Response.accepts
2530
- );
2531
- }
2532
- let paymentHeader;
2533
- try {
2534
- paymentHeader = await this.createPaymentHeader(selectedRequirement, this.wallet);
2535
- } catch (error) {
2536
- throw new X402PaymentError(
2537
- `Failed to create payment header: ${error instanceof Error ? error.message : "Unknown error"}`,
2538
- x402Response.accepts
2539
- );
2540
- }
2541
- const retryHeaders = new Headers(headers);
2542
- retryHeaders.set("X-Payment", paymentHeader);
2543
- for (let attempt = 0; attempt <= (options.retries ?? this.retries); attempt++) {
2544
- try {
2545
- const paidResponse = await fetch(url, {
2546
- ...options,
2547
- headers: retryHeaders,
2548
- signal: options.timeout ? AbortSignal.timeout(options.timeout) : void 0
2549
- });
2550
- const paymentInfo = {
2551
- signature: paymentHeader.split(":")[0] ?? "",
2552
- amount,
2553
- recipient: selectedRequirement.payTo,
2554
- token: selectedRequirement.asset,
2555
- network: selectedRequirement.network,
2556
- timestamp: Date.now()
2557
- };
2558
- const response = paidResponse;
2559
- response.paymentInfo = paymentInfo;
2560
- response.x402Requirements = x402Response.accepts;
2561
- this.emit("payment", paymentInfo);
2562
- options.onPayment?.(paymentInfo);
2563
- return response;
2564
- } catch (error) {
2565
- if (attempt === (options.retries ?? this.retries)) {
2566
- throw error;
2567
- }
2568
- await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
2569
- }
2570
- }
2571
- throw new Error("Failed to complete payment request after retries");
2572
- }
2573
- /**
2574
- * Select the best payment requirement based on options
2575
- */
2576
- selectPaymentRequirement(accepts, options) {
2577
- let candidates = [...accepts];
2578
- if (options.preferredNetwork) {
2579
- const networkMatches = candidates.filter(
2580
- (a) => a.network === options.preferredNetwork
2581
- );
2582
- if (networkMatches.length > 0) {
2583
- candidates = networkMatches;
2584
- }
2585
- }
2586
- if (options.preferredToken) {
2587
- const tokenMatches = candidates.filter(
2588
- (a) => a.asset.toLowerCase() === options.preferredToken.toLowerCase()
2589
- );
2590
- if (tokenMatches.length > 0) {
2591
- candidates = tokenMatches;
2592
- }
2593
- }
2594
- const maxPayment = options.maxPayment ?? this.maxPayment;
2595
- candidates = candidates.filter((a) => BigInt(a.maxAmountRequired) <= maxPayment);
2596
- if (candidates.length === 0) {
2597
- return null;
2598
- }
2599
- return candidates.sort(
2600
- (a, b) => Number(BigInt(a.maxAmountRequired) - BigInt(b.maxAmountRequired))
2601
- )[0];
2602
- }
2603
- };
2604
- var X402PaymentError = class extends Error {
2605
- constructor(message, requirements) {
2606
- super(message);
2607
- this.requirements = requirements;
2608
- this.name = "X402PaymentError";
2609
- }
2610
- };
2611
- async function fetchWithX402Payment(url, options, wallet, createPaymentHeader, paymentOptions) {
2612
- const client = new FetchWithPaymentClient({
2613
- wallet,
2614
- createPaymentHeader,
2615
- maxPayment: paymentOptions?.maxPayment,
2616
- preferredNetwork: paymentOptions?.preferredNetwork,
2617
- preferredToken: paymentOptions?.preferredToken,
2618
- timeout: paymentOptions?.timeout,
2619
- retries: paymentOptions?.retries
2620
- });
2621
- return client.fetch(url, {
2622
- ...options,
2623
- ...paymentOptions
2624
- });
2625
- }
2626
- function wrapFetchWithPayment(wallet, createPaymentHeader, defaultOptions) {
2627
- const client = new FetchWithPaymentClient({
2628
- wallet,
2629
- createPaymentHeader,
2630
- ...defaultOptions
2631
- });
2632
- return (url, options) => client.fetch(url, options);
2633
- }
2634
- var X402AnalyticsTracker = class extends EventEmitter {
2635
- constructor(options = {}) {
2636
- super();
2637
- this.options = options;
2638
- }
2639
- paymentEvents = [];
2640
- agentEarnings = /* @__PURE__ */ new Map();
2641
- agentCallCounts = /* @__PURE__ */ new Map();
2642
- tokenVolumes = /* @__PURE__ */ new Map();
2643
- metricsTimer;
2644
- isActive = false;
2645
- // Integration with existing analytics system
2646
- analyticsStreamer;
2647
- analyticsAggregator;
2648
- /**
2649
- * Start analytics tracking
2650
- */
2651
- start() {
2652
- if (this.isActive) {
2653
- console.warn("x402 analytics tracker is already active");
2654
- return;
2655
- }
2656
- this.isActive = true;
2657
- if (this.options.metricsInterval) {
2658
- this.metricsTimer = setInterval(() => {
2659
- this.aggregateAndEmitMetrics();
2660
- }, this.options.metricsInterval);
2661
- }
2662
- this.emit("started");
2663
- }
2664
- /**
2665
- * Stop analytics tracking
2666
- */
2667
- stop() {
2668
- this.isActive = false;
2669
- if (this.metricsTimer) {
2670
- clearInterval(this.metricsTimer);
2671
- this.metricsTimer = void 0;
2672
- }
2673
- this.emit("stopped");
2674
- }
2675
- /**
2676
- * Record a new x402 payment event
2677
- */
2678
- recordPayment(event) {
2679
- if (!this.isActive) return;
2680
- this.paymentEvents.push(event);
2681
- if (event.agent && event.status === "confirmed") {
2682
- const currentEarnings = this.agentEarnings.get(event.agent) ?? 0n;
2683
- this.agentEarnings.set(event.agent, currentEarnings + event.amount);
2684
- const currentCalls = this.agentCallCounts.get(event.agent) ?? 0;
2685
- this.agentCallCounts.set(event.agent, currentCalls + 1);
2686
- }
2687
- if (event.status === "confirmed") {
2688
- const currentVolume = this.tokenVolumes.get(event.token) ?? 0n;
2689
- this.tokenVolumes.set(event.token, currentVolume + event.amount);
2690
- }
2691
- this.emit("payment", event);
2692
- if (this.options.onPayment) {
2693
- this.options.onPayment(event);
2694
- }
2695
- this.pruneOldEvents();
2696
- }
2697
- /**
2698
- * Record payment from transaction signature
2699
- */
2700
- async recordPaymentFromSignature(signature, payer, recipient, amount, token, agent) {
2701
- const event = {
2702
- signature,
2703
- timestamp: BigInt(Date.now()),
2704
- payer,
2705
- recipient,
2706
- amount,
2707
- token,
2708
- agent,
2709
- status: "pending"
2710
- };
2711
- this.recordPayment(event);
2712
- }
2713
- /**
2714
- * Update payment status
2715
- */
2716
- updatePaymentStatus(signature, status, metadata) {
2717
- const event = this.paymentEvents.find((e) => e.signature === signature);
2718
- if (event) {
2719
- event.status = status;
2720
- if (metadata) {
2721
- event.metadata = { ...event.metadata, ...metadata };
2722
- }
2723
- this.emit("paymentStatusChanged", event);
2724
- }
2725
- }
2726
- /**
2727
- * Get current metrics
2728
- */
2729
- getMetrics(periodSeconds) {
2730
- const now = BigInt(Date.now());
2731
- const startTime = periodSeconds ? now - BigInt(periodSeconds * 1e3) : this.getOldestEventTimestamp();
2732
- const periodEvents = this.paymentEvents.filter((e) => e.timestamp >= startTime);
2733
- const total = periodEvents.length;
2734
- const successful = periodEvents.filter((e) => e.status === "confirmed").length;
2735
- const failed = periodEvents.filter((e) => e.status === "failed").length;
2736
- const pending = periodEvents.filter((e) => e.status === "pending").length;
2737
- const successfulEvents = periodEvents.filter((e) => e.status === "confirmed");
2738
- const totalVolume = successfulEvents.reduce((sum, e) => sum + e.amount, 0n);
2739
- const averageVolume = successful > 0 ? totalVolume / BigInt(successful) : 0n;
2740
- const volumeByToken = /* @__PURE__ */ new Map();
2741
- for (const event of successfulEvents) {
2742
- const current = volumeByToken.get(event.token) ?? 0n;
2743
- volumeByToken.set(event.token, current + event.amount);
2744
- }
2745
- const activeAgents = new Set(
2746
- periodEvents.filter((e) => e.agent).map((e) => e.agent)
2747
- );
2748
- const topEarners = Array.from(this.agentEarnings.entries()).map(([agent, earnings]) => ({
2749
- agent,
2750
- earnings,
2751
- callCount: this.agentCallCounts.get(agent) ?? 0
2752
- })).sort((a, b) => Number(b.earnings - a.earnings)).slice(0, 10);
2753
- const confirmedEvents = periodEvents.filter((e) => e.status === "confirmed");
2754
- const confirmationTimes = confirmedEvents.map((e) => Number(e.metadata?.confirmationTime ?? 0)).filter((t) => t > 0);
2755
- const averageConfirmationTime = confirmationTimes.length > 0 ? confirmationTimes.reduce((a, b) => a + b, 0) / confirmationTimes.length : 0;
2756
- const successRate = total > 0 ? successful / total * 100 : 0;
2757
- const errorRate = total > 0 ? failed / total * 100 : 0;
2758
- return {
2759
- period: {
2760
- start: startTime,
2761
- end: now
2762
- },
2763
- payments: {
2764
- total,
2765
- successful,
2766
- failed,
2767
- pending
2768
- },
2769
- volume: {
2770
- total: totalVolume,
2771
- average: averageVolume,
2772
- byToken: volumeByToken
2773
- },
2774
- agents: {
2775
- totalActive: activeAgents.size,
2776
- topEarners
2777
- },
2778
- performance: {
2779
- averageConfirmationTime,
2780
- successRate,
2781
- errorRate
2782
- }
2783
- };
2784
- }
2785
- /**
2786
- * Get agent earnings
2787
- */
2788
- getAgentEarnings(agent) {
2789
- const totalEarnings = this.agentEarnings.get(agent) ?? 0n;
2790
- const totalCalls = this.agentCallCounts.get(agent) ?? 0;
2791
- const averagePerCall = totalCalls > 0 ? totalEarnings / BigInt(totalCalls) : 0n;
2792
- return {
2793
- totalEarnings,
2794
- totalCalls,
2795
- averagePerCall
2796
- };
2797
- }
2798
- /**
2799
- * Get token volume
2800
- */
2801
- getTokenVolume(token) {
2802
- return this.tokenVolumes.get(token) ?? 0n;
2803
- }
2804
- /**
2805
- * Get payment history for agent
2806
- */
2807
- getAgentPaymentHistory(agent, limit) {
2808
- const agentEvents = this.paymentEvents.filter((e) => e.agent === agent).sort((a, b) => Number(b.timestamp - a.timestamp));
2809
- return limit ? agentEvents.slice(0, limit) : agentEvents;
2810
- }
2811
- /**
2812
- * Get recent payments
2813
- */
2814
- getRecentPayments(limit = 100) {
2815
- return this.paymentEvents.slice(-limit).sort((a, b) => Number(b.timestamp - a.timestamp));
2816
- }
2817
- /**
2818
- * Integrate with existing analytics streamer
2819
- */
2820
- integrateWithStreamer(streamer) {
2821
- this.analyticsStreamer = streamer;
2822
- streamer.on("transactionAnalytics", (event) => {
2823
- if (this.isX402Transaction(event)) {
2824
- this.recordPaymentFromAnalyticsEvent(event);
2825
- }
2826
- });
2827
- }
2828
- /**
2829
- * Integrate with existing analytics aggregator
2830
- */
2831
- integrateWithAggregator(aggregator) {
2832
- this.analyticsAggregator = aggregator;
2833
- this.on("payment", (event) => {
2834
- if (event.status === "confirmed" && this.analyticsAggregator) {
2835
- const txEvent = {
2836
- transactionType: "x402_payment",
2837
- amount: event.amount,
2838
- from: event.payer,
2839
- to: event.recipient,
2840
- status: "completed",
2841
- timestamp: BigInt(event.timestamp),
2842
- blockHeight: 0n
2843
- // Would be populated from actual blockchain data
2844
- };
2845
- this.analyticsAggregator.processTransactionEvent(txEvent);
2846
- }
2847
- });
2848
- }
2849
- /**
2850
- * Get aggregated metrics from integrated aggregator
2851
- */
2852
- getAggregatedMetrics() {
2853
- return this.analyticsAggregator?.aggregate() ?? null;
2854
- }
2855
- // Private helper methods
2856
- aggregateAndEmitMetrics() {
2857
- try {
2858
- const metrics = this.getMetrics();
2859
- this.emit("metrics", metrics);
2860
- if (this.options.onMetrics) {
2861
- this.options.onMetrics(metrics);
2862
- }
2863
- } catch (error) {
2864
- this.handleError(error);
2865
- }
2866
- }
2867
- pruneOldEvents() {
2868
- if (!this.options.retentionPeriod) return;
2869
- const cutoffTime = BigInt(Date.now()) - BigInt(this.options.retentionPeriod * 1e3);
2870
- this.paymentEvents = this.paymentEvents.filter((e) => e.timestamp > cutoffTime);
2871
- }
2872
- getOldestEventTimestamp() {
2873
- if (this.paymentEvents.length === 0) {
2874
- return BigInt(Date.now());
2875
- }
2876
- return this.paymentEvents[0].timestamp;
2877
- }
2878
- isX402Transaction(event) {
2879
- return event.transactionType === "x402_payment" || event.transactionType === "payment";
2880
- }
2881
- recordPaymentFromAnalyticsEvent(event) {
2882
- const paymentEvent = {
2883
- signature: "",
2884
- // Not available in TransactionAnalyticsEvent
2885
- timestamp: BigInt(event.timestamp),
2886
- payer: event.from,
2887
- recipient: event.to,
2888
- amount: event.amount,
2889
- token: "11111111111111111111111111111111",
2890
- // Would parse from event
2891
- status: event.status === "completed" ? "confirmed" : "failed"
2892
- };
2893
- this.recordPayment(paymentEvent);
2894
- }
2895
- handleError(error) {
2896
- this.emit("error", error);
2897
- if (this.options.onError) {
2898
- this.options.onError(error);
2899
- }
2900
- }
2901
- /**
2902
- * Clear all tracked data
2903
- */
2904
- clearData() {
2905
- this.paymentEvents = [];
2906
- this.agentEarnings.clear();
2907
- this.agentCallCounts.clear();
2908
- this.tokenVolumes.clear();
2909
- }
2910
- /**
2911
- * Get tracker statistics
2912
- */
2913
- getStats() {
2914
- return {
2915
- eventsTracked: this.paymentEvents.length,
2916
- agentsTracked: this.agentEarnings.size,
2917
- tokensTracked: this.tokenVolumes.size,
2918
- isActive: this.isActive
2919
- };
2920
- }
2921
- };
2922
- function createX402AnalyticsTracker(options) {
2923
- return new X402AnalyticsTracker(options);
2924
- }
2925
- var PaymentStreamingManager = class extends EventEmitter {
2926
- streams;
2927
- intervals;
2928
- x402Client;
2929
- connection;
2930
- constructor(x402Client, connection) {
2931
- super();
2932
- this.streams = /* @__PURE__ */ new Map();
2933
- this.intervals = /* @__PURE__ */ new Map();
2934
- this.x402Client = x402Client;
2935
- this.connection = connection;
2936
- }
2937
- /**
2938
- * Create a new payment stream
2939
- */
2940
- async createStream(config) {
2941
- const streamId = this.generateStreamId(config);
2942
- this.validateStreamConfig(config);
2943
- const stream = {
2944
- id: streamId,
2945
- config,
2946
- status: "active",
2947
- amountPaid: 0n,
2948
- payments: [],
2949
- startedAt: Date.now(),
2950
- nextPaymentAt: Date.now() + config.intervalMs
2951
- };
2952
- this.streams.set(streamId, stream);
2953
- this.startStreamInterval(stream);
2954
- this.emit("stream_created", stream);
2955
- return stream;
2956
- }
2957
- /**
2958
- * Pause a payment stream
2959
- */
2960
- pauseStream(streamId) {
2961
- const stream = this.streams.get(streamId);
2962
- if (!stream) {
2963
- throw new Error(`Stream ${streamId} not found`);
2964
- }
2965
- if (stream.status !== "active") {
2966
- throw new Error(`Stream ${streamId} is not active`);
2967
- }
2968
- this.stopStreamInterval(streamId);
2969
- stream.status = "paused";
2970
- this.emit("stream_paused", stream);
2971
- }
2972
- /**
2973
- * Resume a paused payment stream
2974
- */
2975
- resumeStream(streamId) {
2976
- const stream = this.streams.get(streamId);
2977
- if (!stream) {
2978
- throw new Error(`Stream ${streamId} not found`);
2979
- }
2980
- if (stream.status !== "paused") {
2981
- throw new Error(`Stream ${streamId} is not paused`);
2982
- }
2983
- stream.status = "active";
2984
- stream.nextPaymentAt = Date.now() + stream.config.intervalMs;
2985
- this.startStreamInterval(stream);
2986
- this.emit("stream_resumed", stream);
2987
- }
2988
- /**
2989
- * Cancel a payment stream
2990
- */
2991
- cancelStream(streamId) {
2992
- const stream = this.streams.get(streamId);
2993
- if (!stream) {
2994
- throw new Error(`Stream ${streamId} not found`);
202
+ signature,
203
+ merchant,
204
+ payer,
205
+ amount,
206
+ success,
207
+ timestamp,
208
+ network: this.network,
209
+ responseTimeMs,
210
+ metadata
211
+ };
212
+ } catch (error) {
213
+ console.error("[X402 Indexer] Failed to extract payment data:", error);
214
+ return null;
2995
215
  }
2996
- this.stopStreamInterval(streamId);
2997
- stream.status = "cancelled";
2998
- stream.endedAt = Date.now();
2999
- this.emit("stream_cancelled", stream);
3000
- }
3001
- /**
3002
- * Get stream by ID
3003
- */
3004
- getStream(streamId) {
3005
- return this.streams.get(streamId);
3006
- }
3007
- /**
3008
- * Get all streams
3009
- */
3010
- getAllStreams() {
3011
- return Array.from(this.streams.values());
3012
216
  }
3013
- /**
3014
- * Get active streams
3015
- */
3016
- getActiveStreams() {
3017
- return Array.from(this.streams.values()).filter((s) => s.status === "active");
217
+ };
218
+
219
+ // src/index.ts
220
+ init_reputation_tags();
221
+ init_MultiSourceAggregator();
222
+ var TIMESTAMP_TOLERANCE_MS = 5 * 60 * 1e3;
223
+ var SIGNATURE_HEADER = "x-payai-signature";
224
+ var TIMESTAMP_HEADER = "x-payai-timestamp";
225
+ var PayAIWebhookHandler = class extends EventEmitter {
226
+ options;
227
+ verifySignatures;
228
+ authorizationModule;
229
+ payAIFacilitatorAddress;
230
+ constructor(options = {}, authorizationModule, payAIFacilitatorAddress) {
231
+ super();
232
+ this.options = options;
233
+ this.verifySignatures = options.verifySignatures ?? process.env.NODE_ENV === "production";
234
+ this.authorizationModule = authorizationModule;
235
+ this.payAIFacilitatorAddress = payAIFacilitatorAddress;
3018
236
  }
237
+ // =====================================================
238
+ // PUBLIC METHODS
239
+ // =====================================================
3019
240
  /**
3020
- * Complete a milestone
241
+ * Handle an incoming webhook request
242
+ *
243
+ * @param request - The incoming HTTP request (must have headers and body)
244
+ * @returns Processing result
3021
245
  */
3022
- async completeMilestone(streamId, milestoneId) {
3023
- const stream = this.streams.get(streamId);
3024
- if (!stream) {
3025
- throw new Error(`Stream ${streamId} not found`);
3026
- }
3027
- const milestone = stream.config.milestones?.find((m) => m.id === milestoneId);
3028
- if (!milestone) {
3029
- throw new Error(`Milestone ${milestoneId} not found`);
3030
- }
3031
- if (milestone.completed) {
3032
- throw new Error(`Milestone ${milestoneId} already completed`);
3033
- }
3034
- const conditionMet = await milestone.condition();
3035
- if (!conditionMet) {
3036
- throw new Error(`Milestone ${milestoneId} condition not met`);
3037
- }
246
+ async handleWebhook(request) {
3038
247
  try {
3039
- const paymentSignature = await this.makePayment(stream, milestone.amount, milestoneId);
3040
- milestone.completed = true;
3041
- milestone.completedAt = Date.now();
3042
- this.emit("milestone_completed", {
3043
- streamId,
3044
- milestoneId,
3045
- signature: paymentSignature
3046
- });
248
+ const payload = typeof request.body === "string" ? JSON.parse(request.body) : request.body;
249
+ if (this.verifySignatures && this.options.webhookSecret) {
250
+ const bodyStr = typeof request.body === "string" ? request.body : JSON.stringify(request.body);
251
+ const verification = await this.verifySignature(
252
+ request.headers,
253
+ bodyStr
254
+ );
255
+ if (!verification.valid) {
256
+ return {
257
+ success: false,
258
+ error: verification.error ?? "Invalid signature"
259
+ };
260
+ }
261
+ }
262
+ return await this.processPayload(payload);
3047
263
  } catch (error) {
3048
- this.emit("milestone_failed", {
3049
- streamId,
3050
- milestoneId,
3051
- error
3052
- });
3053
- throw error;
264
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
265
+ this.emit("error", new Error(`Webhook processing failed: ${errorMessage}`));
266
+ return {
267
+ success: false,
268
+ error: errorMessage
269
+ };
3054
270
  }
3055
271
  }
3056
272
  /**
3057
- * Cleanup: Stop all streams and clear intervals
273
+ * Verify webhook signature
3058
274
  */
3059
- cleanup() {
3060
- for (const streamId of this.intervals.keys()) {
3061
- this.stopStreamInterval(streamId);
275
+ async verifySignature(headers, body) {
276
+ const getHeader = (name) => {
277
+ if (headers instanceof Headers) {
278
+ return headers.get(name) ?? void 0;
279
+ }
280
+ return headers[name];
281
+ };
282
+ const signature = getHeader(SIGNATURE_HEADER);
283
+ const timestamp = getHeader(TIMESTAMP_HEADER);
284
+ if (!signature) {
285
+ return { valid: false, error: "Missing signature header" };
3062
286
  }
3063
- this.streams.clear();
3064
- this.intervals.clear();
3065
- }
3066
- // Private methods
3067
- generateStreamId(config) {
3068
- const timestamp = Date.now();
3069
- const hash = `${config.agentAddress}-${config.clientAddress}-${timestamp}`;
3070
- return Buffer.from(hash).toString("base64").slice(0, 16);
3071
- }
3072
- validateStreamConfig(config) {
3073
- if (config.totalAmount <= 0n) {
3074
- throw new Error("Total amount must be positive");
287
+ if (!timestamp) {
288
+ return { valid: false, error: "Missing timestamp header" };
3075
289
  }
3076
- if (config.intervalMs <= 0) {
3077
- throw new Error("Interval must be positive");
290
+ const timestampMs = parseInt(timestamp, 10);
291
+ if (isNaN(timestampMs)) {
292
+ return { valid: false, error: "Invalid timestamp format" };
293
+ }
294
+ const now = Date.now();
295
+ if (Math.abs(now - timestampMs) > TIMESTAMP_TOLERANCE_MS) {
296
+ return { valid: false, error: "Timestamp too old or too far in future" };
3078
297
  }
3079
- if (config.durationMs <= 0) {
3080
- throw new Error("Duration must be positive");
298
+ if (!this.options.webhookSecret) {
299
+ return { valid: false, error: "Webhook secret not configured" };
3081
300
  }
3082
- if (config.amountPerInterval <= 0n) {
3083
- throw new Error("Amount per interval must be positive");
301
+ const expectedSignature = this.computeSignature(
302
+ timestamp,
303
+ body,
304
+ this.options.webhookSecret
305
+ );
306
+ const signatureBuffer = Buffer.from(signature, "hex");
307
+ const expectedBuffer = Buffer.from(expectedSignature, "hex");
308
+ if (signatureBuffer.length !== expectedBuffer.length) {
309
+ return { valid: false, error: "Invalid signature" };
3084
310
  }
3085
- const maxPayments = Math.ceil(config.durationMs / config.intervalMs);
3086
- const totalViaInterval = config.amountPerInterval * BigInt(maxPayments);
3087
- const milestoneTotal = config.milestones?.reduce((sum, m) => sum + m.amount, 0n) ?? 0n;
3088
- if (totalViaInterval + milestoneTotal > config.totalAmount * 110n / 100n) {
3089
- throw new Error("Payment schedule exceeds total amount (with 10% tolerance)");
311
+ if (!timingSafeEqual(signatureBuffer, expectedBuffer)) {
312
+ return { valid: false, error: "Invalid signature" };
3090
313
  }
314
+ return { valid: true };
3091
315
  }
3092
- startStreamInterval(stream) {
3093
- const interval = setInterval(async () => {
3094
- await this.processPayment(stream);
3095
- }, stream.config.intervalMs);
3096
- this.intervals.set(stream.id, interval);
316
+ /**
317
+ * Convert a PayAI payment to a reputation record
318
+ */
319
+ paymentToReputationRecord(data) {
320
+ return {
321
+ agentAddress: data.merchant,
322
+ paymentSignature: data.transactionSignature,
323
+ amount: BigInt(data.amount),
324
+ success: data.success ?? data.status === "settled",
325
+ responseTimeMs: data.responseTimeMs ?? 0,
326
+ payerAddress: data.payer,
327
+ timestamp: new Date(data.settledAt ?? data.verifiedAt ?? Date.now()),
328
+ network: data.network
329
+ };
3097
330
  }
3098
- stopStreamInterval(streamId) {
3099
- const interval = this.intervals.get(streamId);
3100
- if (interval) {
3101
- clearInterval(interval);
3102
- this.intervals.delete(streamId);
331
+ // =====================================================
332
+ // PRIVATE METHODS
333
+ // =====================================================
334
+ /**
335
+ * Process a verified webhook payload
336
+ */
337
+ async processPayload(payload) {
338
+ const { type, data } = payload;
339
+ switch (type) {
340
+ case "payment.verified":
341
+ this.emit("payment:verified", data);
342
+ await this.options.onPaymentVerified?.(data);
343
+ break;
344
+ case "payment.settled":
345
+ this.emit("payment:settled", data);
346
+ await this.options.onPaymentSettled?.(data);
347
+ if (this.options.onRecordReputation) {
348
+ if (this.authorizationModule && this.payAIFacilitatorAddress) {
349
+ const isAuthorized = await this.verifyOnChainAuthorization(data.merchant);
350
+ if (!isAuthorized) {
351
+ return {
352
+ success: false,
353
+ eventType: type,
354
+ paymentId: data.paymentId,
355
+ error: "Agent has not authorized PayAI facilitator to update reputation",
356
+ reputationRecorded: false
357
+ };
358
+ }
359
+ }
360
+ const record = this.paymentToReputationRecord(data);
361
+ await this.options.onRecordReputation(record);
362
+ this.emit("reputation:recorded", record);
363
+ return {
364
+ success: true,
365
+ eventType: type,
366
+ paymentId: data.paymentId,
367
+ reputationRecorded: true
368
+ };
369
+ }
370
+ break;
371
+ case "payment.failed":
372
+ this.emit("payment:failed", data);
373
+ await this.options.onPaymentFailed?.(data);
374
+ if (this.options.onRecordReputation) {
375
+ const record = this.paymentToReputationRecord(data);
376
+ record.success = false;
377
+ await this.options.onRecordReputation(record);
378
+ this.emit("reputation:recorded", record);
379
+ return {
380
+ success: true,
381
+ eventType: type,
382
+ paymentId: data.paymentId,
383
+ reputationRecorded: true
384
+ };
385
+ }
386
+ break;
387
+ case "payment.refunded":
388
+ break;
389
+ default:
390
+ return {
391
+ success: false,
392
+ error: `Unknown event type: ${type}`
393
+ };
3103
394
  }
395
+ return {
396
+ success: true,
397
+ eventType: type,
398
+ paymentId: data.paymentId,
399
+ reputationRecorded: false
400
+ };
3104
401
  }
3105
- async processPayment(stream) {
3106
- if (stream.status !== "active") {
3107
- return;
3108
- }
3109
- if (stream.amountPaid >= stream.config.totalAmount) {
3110
- this.completeStream(stream);
3111
- return;
3112
- }
3113
- if (Date.now() >= stream.startedAt + stream.config.durationMs) {
3114
- this.completeStream(stream);
3115
- return;
402
+ /**
403
+ * Verify on-chain authorization for an agent
404
+ *
405
+ * Checks if the agent has pre-authorized the PayAI facilitator
406
+ * to update their reputation on-chain.
407
+ */
408
+ async verifyOnChainAuthorization(agentAddress) {
409
+ if (!this.authorizationModule || !this.payAIFacilitatorAddress) {
410
+ return true;
3116
411
  }
3117
412
  try {
3118
- const amount = stream.config.amountPerInterval;
3119
- const signature = await this.makePayment(stream, amount);
3120
- stream.lastPaymentAt = Date.now();
3121
- stream.nextPaymentAt = Date.now() + stream.config.intervalMs;
3122
- this.emit("payment_processed", {
3123
- streamId: stream.id,
3124
- amount,
3125
- signature
3126
- });
3127
- } catch (error) {
3128
- this.emit("payment_failed", {
3129
- streamId: stream.id,
3130
- error
3131
- });
3132
- if (stream.config.autoResume !== true) {
3133
- stream.status = "failed";
3134
- stream.error = error;
3135
- stream.endedAt = Date.now();
3136
- this.stopStreamInterval(stream.id);
413
+ const authorization = await this.authorizationModule.fetchAuthorization(
414
+ agentAddress,
415
+ this.payAIFacilitatorAddress
416
+ );
417
+ if (!authorization) {
418
+ return false;
3137
419
  }
420
+ const status = this.authorizationModule.getAuthorizationStatus(
421
+ authorization,
422
+ authorization.currentIndex
423
+ );
424
+ return status.isValid;
425
+ } catch (error) {
426
+ console.error("Failed to verify on-chain authorization:", error);
427
+ return false;
3138
428
  }
3139
429
  }
3140
- async makePayment(stream, amount, milestoneId) {
3141
- const paymentRequest = this.x402Client.createPaymentRequest({
3142
- amount,
3143
- token: stream.config.tokenMint,
3144
- description: milestoneId ? `Stream ${stream.id} - Milestone ${milestoneId}` : `Stream ${stream.id} - Interval payment`,
3145
- metadata: {
3146
- streamId: stream.id,
3147
- ...milestoneId && { milestoneId }
3148
- }
3149
- });
3150
- const receipt = await this.x402Client.pay(paymentRequest);
3151
- const payment = {
3152
- timestamp: Date.now(),
3153
- amount,
3154
- signature: receipt.signature,
3155
- milestoneId,
3156
- success: true
3157
- };
3158
- stream.payments.push(payment);
3159
- stream.amountPaid += amount;
3160
- return receipt.signature;
3161
- }
3162
- completeStream(stream) {
3163
- this.stopStreamInterval(stream.id);
3164
- stream.status = "completed";
3165
- stream.endedAt = Date.now();
3166
- this.emit("stream_completed", stream);
430
+ /**
431
+ * Compute HMAC-SHA256 signature for a webhook payload
432
+ */
433
+ computeSignature(timestamp, body, secret) {
434
+ const signedPayload = `${timestamp}.${body}`;
435
+ const hmac = createHmac("sha256", secret);
436
+ hmac.update(signedPayload);
437
+ return hmac.digest("hex");
3167
438
  }
3168
439
  };
3169
- var A2AClient = class extends EventEmitter {
3170
- rpc;
3171
- programId;
3172
- wallet;
3173
- constructor(options, wallet) {
440
+ function createPayAIWebhookHandler(options = {}) {
441
+ return new PayAIWebhookHandler(options);
442
+ }
443
+ function generateTestWebhookSignature(body, secret, timestamp) {
444
+ const ts = (timestamp ?? Date.now()).toString();
445
+ const signedPayload = `${ts}.${body}`;
446
+ const hmac = createHmac("sha256", secret);
447
+ hmac.update(signedPayload);
448
+ return {
449
+ signature: hmac.digest("hex"),
450
+ timestamp: ts
451
+ };
452
+ }
453
+ function createMockPayAIWebhook(overrides = {}) {
454
+ return {
455
+ id: `evt_${Date.now()}`,
456
+ type: "payment.settled",
457
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
458
+ data: {
459
+ paymentId: `pay_${Date.now()}`,
460
+ transactionSignature: `${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`,
461
+ network: "solana",
462
+ payer: "PayerWalletAddress111111111111111111111111",
463
+ merchant: "MerchantAgentAddress11111111111111111111",
464
+ amount: "1000000",
465
+ // 1 USDC
466
+ asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
467
+ assetSymbol: "USDC",
468
+ status: "settled",
469
+ resource: "https://api.example.com/ai/generate",
470
+ responseTimeMs: 250,
471
+ httpStatusCode: 200,
472
+ success: true,
473
+ settledAt: (/* @__PURE__ */ new Date()).toISOString(),
474
+ ...overrides
475
+ }
476
+ };
477
+ }
478
+ var DEFAULT_MARKETPLACE_URL = "https://marketplace.payai.network/api";
479
+ var PayAIAgentSync = class extends EventEmitter {
480
+ config;
481
+ constructor(config = {}) {
3174
482
  super();
3175
- this.rpc = createSolanaRpc(options.rpcEndpoint);
3176
- this.programId = options.programId ?? GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS;
3177
- this.wallet = wallet;
483
+ this.config = {
484
+ marketplaceUrl: config.marketplaceUrl ?? DEFAULT_MARKETPLACE_URL,
485
+ apiKey: config.apiKey,
486
+ network: config.network ?? "solana",
487
+ timeout: config.timeout ?? 3e4
488
+ };
3178
489
  }
490
+ // =====================================================
491
+ // PUBLIC METHODS
492
+ // =====================================================
3179
493
  /**
3180
- * Create a new A2A communication session
3181
- *
3182
- * Establishes a secure communication channel between two agents.
494
+ * Register a GhostSpeak agent with PayAI marketplace
3183
495
  *
3184
- * @param config - Session configuration
3185
- * @returns Session details including address
3186
- *
3187
- * @example
3188
- * ```typescript
3189
- * const session = await a2aClient.createSession({
3190
- * responder: 'AgentBpubkey...',
3191
- * sessionType: 'data_processing',
3192
- * metadata: 'Processing financial data',
3193
- * expiresIn: 7200 // 2 hours
3194
- * })
3195
- * console.log('Session created:', session.address)
3196
- * ```
496
+ * @param agent - Agent data from GhostSpeak
497
+ * @returns Registration result
3197
498
  */
3198
- async createSession(config) {
499
+ async registerAgent(agent) {
3199
500
  try {
3200
- const now = Math.floor(Date.now() / 1e3);
3201
- const expiresAt = now + (config.expiresIn ?? 3600);
3202
- const sessionId = BigInt(Date.now());
3203
- const instruction = await getCreateA2aSessionInstructionAsync({
3204
- creator: this.wallet,
3205
- sessionId,
3206
- initiator: this.wallet.address,
3207
- responder: config.responder,
3208
- sessionType: config.sessionType,
3209
- metadata: config.metadata ?? "",
3210
- expiresAt: BigInt(expiresAt)
3211
- }, { programAddress: this.programId });
3212
- const signature = await this.sendTransaction([instruction]);
3213
- const sessionAddress = instruction.accounts[0].address;
3214
- this.emit("session_created", {
3215
- type: "session_created",
3216
- timestamp: Date.now(),
3217
- data: { sessionAddress, signature }
501
+ const registration = this.toPayAIRegistration(agent);
502
+ const response = await this.makeRequest("/merchants/register", {
503
+ method: "POST",
504
+ body: JSON.stringify(registration)
505
+ });
506
+ if (!response.ok) {
507
+ const error = await response.text();
508
+ return {
509
+ success: false,
510
+ error: `Registration failed: ${error}`
511
+ };
512
+ }
513
+ const data = await response.json();
514
+ this.emit("agent:registered", {
515
+ agentAddress: agent.address,
516
+ agentId: data.agentId
3218
517
  });
3219
- const session = await fetchA2ASession(this.rpc, sessionAddress);
3220
518
  return {
3221
- ...session.data,
3222
- address: sessionAddress
519
+ success: true,
520
+ agentId: data.agentId,
521
+ marketplaceUrl: data.url
3223
522
  };
3224
523
  } catch (error) {
3225
- const errorMessage = error instanceof Error ? error.message : String(error);
3226
- this.emit("error", {
3227
- type: "error",
3228
- timestamp: Date.now(),
524
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
525
+ return {
526
+ success: false,
3229
527
  error: errorMessage
3230
- });
3231
- throw new Error(`Failed to create A2A session: ${errorMessage}`);
528
+ };
3232
529
  }
3233
530
  }
3234
531
  /**
3235
- * Send a message in an A2A session
3236
- *
3237
- * Sends structured messages between agents with automatic context management.
532
+ * Update an agent's registration on PayAI marketplace
3238
533
  *
3239
- * @param params - Message parameters
3240
- * @returns Transaction signature
3241
- *
3242
- * @example
3243
- * ```typescript
3244
- * await a2aClient.sendMessage({
3245
- * sessionAddress: session.address,
3246
- * content: 'Processing complete. Results: {...}',
3247
- * messageType: 'result'
3248
- * })
3249
- * ```
534
+ * @param agentId - PayAI agent ID
535
+ * @param agent - Updated agent data
536
+ * @returns Update result
3250
537
  */
3251
- async sendMessage(params) {
538
+ async updateAgent(agentId, agent) {
3252
539
  try {
3253
- const messageId = BigInt(Date.now());
3254
- const sessionId = BigInt(Date.now());
3255
- const timestamp = BigInt(Math.floor(Date.now() / 1e3));
3256
- const instruction = getSendA2aMessageInstruction({
3257
- message: await this.deriveMessageAddress(params.sessionAddress),
3258
- session: params.sessionAddress,
3259
- sender: this.wallet,
3260
- messageId,
3261
- sessionId,
3262
- senderArg: this.wallet.address,
3263
- content: params.content,
3264
- messageType: params.messageType ?? "text",
3265
- timestamp
3266
- }, { programAddress: this.programId });
3267
- const signature = await this.sendTransaction([instruction]);
3268
- this.emit("message_sent", {
3269
- type: "message_sent",
3270
- timestamp: Date.now(),
3271
- data: { signature, content: params.content }
540
+ const response = await this.makeRequest(`/merchants/${agentId}`, {
541
+ method: "PATCH",
542
+ body: JSON.stringify(agent)
3272
543
  });
3273
- return signature;
544
+ if (!response.ok) {
545
+ const error = await response.text();
546
+ return {
547
+ success: false,
548
+ error: `Update failed: ${error}`
549
+ };
550
+ }
551
+ this.emit("agent:updated", { agentId });
552
+ return {
553
+ success: true,
554
+ agentId
555
+ };
3274
556
  } catch (error) {
3275
- const errorMessage = error instanceof Error ? error.message : String(error);
3276
- this.emit("error", {
3277
- type: "error",
3278
- timestamp: Date.now(),
557
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
558
+ return {
559
+ success: false,
3279
560
  error: errorMessage
3280
- });
3281
- throw new Error(`Failed to send A2A message: ${errorMessage}`);
561
+ };
3282
562
  }
3283
563
  }
3284
564
  /**
3285
- * Update agent status
3286
- *
3287
- * Updates agent availability, capabilities, and status for discovery.
565
+ * Remove an agent from PayAI marketplace
3288
566
  *
3289
- * @param update - Status update
3290
- * @returns Transaction signature
3291
- *
3292
- * @example
3293
- * ```typescript
3294
- * await a2aClient.updateStatus({
3295
- * status: 'busy',
3296
- * capabilities: ['nlp', 'translation'],
3297
- * availability: false
3298
- * })
3299
- * ```
567
+ * @param agentId - PayAI agent ID
568
+ * @returns Removal result
3300
569
  */
3301
- async updateStatus(update) {
570
+ async removeAgent(agentId) {
3302
571
  try {
3303
- const statusAddress = await this.deriveStatusAddress();
3304
- const instruction = getUpdateA2aStatusInstruction({
3305
- status: statusAddress,
3306
- session: address("11111111111111111111111111111111"),
3307
- // Placeholder - need actual session
3308
- updater: this.wallet,
3309
- statusId: BigInt(Date.now()),
3310
- agent: this.wallet.address,
3311
- statusArg: update.status,
3312
- capabilities: update.capabilities ?? [],
3313
- availability: update.availability ?? true,
3314
- lastUpdated: BigInt(Math.floor(Date.now() / 1e3))
3315
- }, { programAddress: this.programId });
3316
- const signature = await this.sendTransaction([instruction]);
3317
- this.emit("status_updated", {
3318
- type: "status_updated",
3319
- timestamp: Date.now(),
3320
- data: { signature, status: update.status }
572
+ const response = await this.makeRequest(`/merchants/${agentId}`, {
573
+ method: "DELETE"
3321
574
  });
3322
- return signature;
575
+ if (!response.ok) {
576
+ const error = await response.text();
577
+ return {
578
+ success: false,
579
+ error: `Removal failed: ${error}`
580
+ };
581
+ }
582
+ this.emit("agent:removed", { agentId });
583
+ return {
584
+ success: true,
585
+ agentId
586
+ };
3323
587
  } catch (error) {
3324
- const errorMessage = error instanceof Error ? error.message : String(error);
3325
- this.emit("error", {
3326
- type: "error",
3327
- timestamp: Date.now(),
588
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
589
+ return {
590
+ success: false,
3328
591
  error: errorMessage
3329
- });
3330
- throw new Error(`Failed to update A2A status: ${errorMessage}`);
592
+ };
3331
593
  }
3332
594
  }
3333
595
  /**
3334
- * Get session details
3335
- *
3336
- * Fetches current session state from on-chain.
596
+ * Check if an agent is registered on PayAI marketplace
3337
597
  *
3338
- * @param sessionAddress - Session PDA address
3339
- * @returns Session details
598
+ * @param agentAddress - Agent's Solana address
599
+ * @returns Whether agent is registered
3340
600
  */
3341
- async getSession(sessionAddress) {
601
+ async isAgentRegistered(agentAddress) {
3342
602
  try {
3343
- const maybeSession = await fetchMaybeA2ASession(this.rpc, sessionAddress);
3344
- if (!maybeSession.exists) {
3345
- return null;
603
+ const response = await this.makeRequest(
604
+ `/merchants/check?address=${agentAddress}&network=${this.config.network}`
605
+ );
606
+ if (!response.ok) {
607
+ return false;
3346
608
  }
3347
- return {
3348
- ...maybeSession.data,
3349
- address: sessionAddress
3350
- };
3351
- } catch (error) {
3352
- console.error("Failed to fetch A2A session:", error);
3353
- return null;
609
+ const data = await response.json();
610
+ return data.registered;
611
+ } catch {
612
+ return false;
3354
613
  }
3355
614
  }
3356
615
  /**
3357
- * Get message by address
616
+ * Get agent's PayAI marketplace listing
3358
617
  *
3359
- * @param messageAddress - Message PDA address
3360
- * @returns Message data
618
+ * @param agentAddress - Agent's Solana address
619
+ * @returns Agent listing or null
3361
620
  */
3362
- async getMessage(messageAddress) {
621
+ async getAgentListing(agentAddress) {
3363
622
  try {
3364
- const message = await fetchA2AMessage(this.rpc, messageAddress);
3365
- return message.data;
3366
- } catch (error) {
3367
- console.error("Failed to fetch A2A message:", error);
623
+ const response = await this.makeRequest(
624
+ `/merchants/by-address?address=${agentAddress}&network=${this.config.network}`
625
+ );
626
+ if (!response.ok) {
627
+ return null;
628
+ }
629
+ return response.json();
630
+ } catch {
3368
631
  return null;
3369
632
  }
3370
633
  }
3371
634
  /**
3372
- * Get agent status
635
+ * Sync reputation score to PayAI marketplace
636
+ *
637
+ * Updates the agent's reputation score on PayAI based on
638
+ * GhostSpeak reputation calculations.
3373
639
  *
3374
- * @param statusAddress - Status PDA address
3375
- * @returns Status data
640
+ * @param agentId - PayAI agent ID
641
+ * @param reputationScore - New reputation score (0-10000)
642
+ * @returns Update result
3376
643
  */
3377
- async getStatus(statusAddress) {
644
+ async syncReputationScore(agentId, reputationScore) {
3378
645
  try {
3379
- const status = await fetchA2AStatus(this.rpc, statusAddress);
3380
- return status.data;
646
+ const response = await this.makeRequest(`/merchants/${agentId}/reputation`, {
647
+ method: "POST",
648
+ body: JSON.stringify({
649
+ score: reputationScore,
650
+ source: "ghostspeak",
651
+ timestamp: Date.now()
652
+ })
653
+ });
654
+ if (!response.ok) {
655
+ const error = await response.text();
656
+ return {
657
+ success: false,
658
+ error: `Reputation sync failed: ${error}`
659
+ };
660
+ }
661
+ this.emit("reputation:synced", { agentId, reputationScore });
662
+ return {
663
+ success: true,
664
+ agentId
665
+ };
3381
666
  } catch (error) {
3382
- console.error("Failed to fetch A2A status:", error);
3383
- return null;
667
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
668
+ return {
669
+ success: false,
670
+ error: errorMessage
671
+ };
3384
672
  }
3385
673
  }
3386
674
  // =====================================================
3387
- // PRIVATE HELPER METHODS
675
+ // PRIVATE METHODS
3388
676
  // =====================================================
3389
- async sendTransaction(instructions) {
3390
- try {
3391
- const { value: latestBlockhash } = await this.rpc.getLatestBlockhash().send();
3392
- let message = createTransactionMessage({ version: 0 });
3393
- message = setTransactionMessageFeePayer(this.wallet.address, message);
3394
- message = setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message);
3395
- for (const ix of instructions) {
3396
- message = appendTransactionMessageInstruction(ix, message);
3397
- }
3398
- const signedTransaction = await signTransactionMessageWithSigners(message);
3399
- const signatures = Object.values(signedTransaction.signatures);
3400
- if (signatures.length === 0) {
3401
- throw new Error("Transaction has no signatures");
3402
- }
3403
- const signature = signatures[0];
3404
- const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
3405
- await this.rpc.sendTransaction(wireTransaction).send();
3406
- await this.confirmTransaction(signature);
3407
- return signature;
3408
- } catch (error) {
3409
- throw new Error(
3410
- `Transaction failed: ${error instanceof Error ? error.message : String(error)}`
3411
- );
3412
- }
3413
- }
3414
- async confirmTransaction(signature) {
3415
- for (let i = 0; i < 30; i++) {
3416
- const status = await this.rpc.getSignatureStatuses([signature]).send();
3417
- if (status.value[0]?.confirmationStatus === "confirmed" || status.value[0]?.confirmationStatus === "finalized") {
3418
- return;
3419
- }
3420
- await new Promise((resolve) => setTimeout(resolve, 1e3));
3421
- }
3422
- throw new Error("Transaction confirmation timeout");
3423
- }
3424
- async deriveMessageAddress(sessionAddress) {
3425
- return address("11111111111111111111111111111111");
3426
- }
3427
- async deriveStatusAddress() {
3428
- return address("11111111111111111111111111111111");
3429
- }
3430
- };
3431
- function createA2AClient(options, wallet) {
3432
- return new A2AClient(options, wallet);
3433
- }
3434
- var H2AClient = class extends EventEmitter {
3435
- rpc;
3436
- programId;
3437
- wallet;
3438
- constructor(options, wallet) {
3439
- super();
3440
- this.rpc = createSolanaRpc(options.rpcEndpoint);
3441
- this.programId = options.programId ?? GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS;
3442
- this.wallet = wallet;
3443
- }
3444
- /**
3445
- * Create a new communication session with an agent
3446
- *
3447
- * Establishes a communication channel between a human and an agent.
3448
- *
3449
- * @param config - Session configuration
3450
- * @returns Session details including address
3451
- *
3452
- * @throws {Error} Currently not implemented - requires IDL regeneration
3453
- *
3454
- * @example
3455
- * ```typescript
3456
- * const session = await h2aClient.createSession({
3457
- * agentAddress: 'Agent123...',
3458
- * sessionType: 'content_writing',
3459
- * metadata: 'Blog post about AI agents',
3460
- * expiresIn: 7200 // 2 hours
3461
- * })
3462
- * ```
3463
- */
3464
- async createSession(config) {
3465
- const expiresAt = BigInt(Math.floor(Date.now() / 1e3) + (config.expiresIn ?? 3600));
3466
- const sessionId = BigInt(Date.now());
3467
- const initiator = this.wallet.address;
3468
- const [sessionAddress] = await getProgramDerivedAddress({
3469
- programAddress: this.programId,
3470
- seeds: [
3471
- getBytesEncoder().encode(new Uint8Array([99, 111, 109, 109, 95, 115, 101, 115, 115, 105, 111, 110])),
3472
- // 'comm_session'
3473
- getAddressEncoder().encode(initiator)
3474
- ]
3475
- });
3476
- const instruction = await getCreateCommunicationSessionInstructionAsync({
3477
- session: sessionAddress,
3478
- creator: this.wallet,
3479
- sessionId,
3480
- initiator,
3481
- initiatorType: 0 /* Human */,
3482
- responder: config.agentAddress,
3483
- responderType: 1 /* Agent */,
3484
- sessionType: config.sessionType,
3485
- metadata: config.metadata ?? "",
3486
- expiresAt
3487
- }, { programAddress: this.programId });
3488
- const signature = await this.sendTransaction([instruction]);
3489
- this.emit("session_created", {
3490
- type: "session_created",
3491
- timestamp: Date.now(),
3492
- data: {
3493
- address: sessionAddress,
3494
- signature,
3495
- agent: config.agentAddress
3496
- }
3497
- });
3498
- return { address: sessionAddress, signature };
3499
- }
3500
- /**
3501
- * Send a service request to an agent
3502
- *
3503
- * Sends a work request to an agent with optional payment commitment.
3504
- *
3505
- * @param request - Service request parameters
3506
- * @returns Transaction signature
3507
- *
3508
- * @example
3509
- * ```typescript
3510
- * await h2aClient.sendServiceRequest({
3511
- * sessionAddress: session.address,
3512
- * content: 'Generate 10 social media posts about web3',
3513
- * messageType: 'service_request',
3514
- * attachments: ['ipfs://QmBrandGuidelines'],
3515
- * paymentAmount: 10_000_000n, // 10 USDC
3516
- * deadline: Date.now() / 1000 + 172800 // 48 hours
3517
- * })
3518
- * ```
3519
- */
3520
- async sendServiceRequest(request) {
3521
- const messageId = BigInt(Date.now());
3522
- const messageIdBytes = new Uint8Array(8);
3523
- const view = new DataView(messageIdBytes.buffer);
3524
- view.setBigUint64(0, messageId, true);
3525
- const [messageAddress] = await getProgramDerivedAddress({
3526
- programAddress: this.programId,
3527
- seeds: [
3528
- getBytesEncoder().encode(new Uint8Array([99, 111, 109, 109, 95, 109, 101, 115, 115, 97, 103, 101])),
3529
- // 'comm_message'
3530
- getAddressEncoder().encode(request.sessionAddress),
3531
- getBytesEncoder().encode(messageIdBytes)
3532
- ]
3533
- });
3534
- const instruction = getSendCommunicationMessageInstruction({
3535
- message: messageAddress,
3536
- session: request.sessionAddress,
3537
- sender: this.wallet,
3538
- messageId,
3539
- senderType: 0 /* Human */,
3540
- content: request.content,
3541
- messageType: request.messageType ?? "service_request",
3542
- attachments: request.attachments ?? []
3543
- }, { programAddress: this.programId });
3544
- const signature = await this.sendTransaction([instruction]);
3545
- this.emit("service_requested", {
3546
- type: "service_requested",
3547
- timestamp: Date.now(),
3548
- data: {
3549
- messageAddress,
3550
- sessionAddress: request.sessionAddress,
3551
- signature
3552
- }
3553
- });
3554
- return signature;
3555
- }
3556
677
  /**
3557
- * Send a message in an existing session
3558
- *
3559
- * Sends a message to an agent with support for file attachments.
3560
- *
3561
- * @param params - Message parameters
3562
- * @returns Transaction signature
678
+ * Convert GhostSpeak agent data to PayAI registration format
3563
679
  */
3564
- async sendMessage(params) {
3565
- const messageId = BigInt(Date.now());
3566
- const messageIdBytes = new Uint8Array(8);
3567
- const view = new DataView(messageIdBytes.buffer);
3568
- view.setBigUint64(0, messageId, true);
3569
- const [messageAddress] = await getProgramDerivedAddress({
3570
- programAddress: this.programId,
3571
- seeds: [
3572
- getBytesEncoder().encode(new Uint8Array([99, 111, 109, 109, 95, 109, 101, 115, 115, 97, 103, 101])),
3573
- // 'comm_message'
3574
- getAddressEncoder().encode(params.sessionAddress),
3575
- getBytesEncoder().encode(messageIdBytes)
3576
- ]
3577
- });
3578
- const instruction = getSendCommunicationMessageInstruction({
3579
- message: messageAddress,
3580
- session: params.sessionAddress,
3581
- sender: this.wallet,
3582
- messageId,
3583
- senderType: 0 /* Human */,
3584
- content: params.content,
3585
- messageType: params.messageType ?? "text",
3586
- attachments: params.attachments ?? []
3587
- }, { programAddress: this.programId });
3588
- const signature = await this.sendTransaction([instruction]);
3589
- this.emit("message_sent", {
3590
- type: "message_sent",
3591
- timestamp: Date.now(),
3592
- data: {
3593
- messageAddress,
3594
- sessionAddress: params.sessionAddress,
3595
- signature
680
+ toPayAIRegistration(agent) {
681
+ return {
682
+ agentAddress: agent.address,
683
+ serviceEndpoint: agent.serviceEndpoint,
684
+ capabilities: agent.capabilities,
685
+ acceptedTokens: agent.acceptedTokens,
686
+ pricing: agent.pricing,
687
+ metadata: {
688
+ name: agent.name,
689
+ description: agent.description,
690
+ logo: agent.logo,
691
+ website: agent.website
3596
692
  }
3597
- });
3598
- return signature;
693
+ };
3599
694
  }
3600
695
  /**
3601
- * Get session details
3602
- *
3603
- * @param sessionAddress - Session PDA address
696
+ * Make an authenticated request to PayAI marketplace
3604
697
  */
3605
- async getSession(sessionAddress) {
3606
- const accountInfo = await this.rpc.getAccountInfo(sessionAddress, { encoding: "base64" }).send();
3607
- if (!accountInfo.value) {
3608
- throw new Error(`Session account not found: ${sessionAddress}`);
698
+ async makeRequest(path, options = {}) {
699
+ const controller = new AbortController();
700
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
701
+ const headers = {
702
+ "Content-Type": "application/json",
703
+ "X-Ghostspeak-Integration": "1.0"
704
+ };
705
+ if (this.config.apiKey) {
706
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
3609
707
  }
3610
- const data = accountInfo.value.data;
3611
- return getCommunicationSessionDataDecoder().decode(
3612
- typeof data === "string" ? Uint8Array.from(Buffer.from(data, "base64")) : new Uint8Array(data)
3613
- );
3614
- }
3615
- // =====================================================
3616
- // PRIVATE HELPER METHODS
3617
- // =====================================================
3618
- async sendTransaction(instructions) {
3619
708
  try {
3620
- const { value: latestBlockhash } = await this.rpc.getLatestBlockhash().send();
3621
- let message = createTransactionMessage({ version: 0 });
3622
- message = setTransactionMessageFeePayer(this.wallet.address, message);
3623
- message = setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message);
3624
- for (const ix of instructions) {
3625
- message = appendTransactionMessageInstruction(ix, message);
3626
- }
3627
- const signedTransaction = await signTransactionMessageWithSigners(message);
3628
- const signatures = Object.values(signedTransaction.signatures);
3629
- if (signatures.length === 0) {
3630
- throw new Error("Transaction has no signatures");
3631
- }
3632
- const signature = signatures[0];
3633
- const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
3634
- await this.rpc.sendTransaction(wireTransaction).send();
3635
- await this.confirmTransaction(signature);
3636
- return signature;
3637
- } catch (error) {
3638
- throw new Error(
3639
- `Transaction failed: ${error instanceof Error ? error.message : String(error)}`
3640
- );
3641
- }
3642
- }
3643
- async confirmTransaction(signature) {
3644
- for (let i = 0; i < 30; i++) {
3645
- const status = await this.rpc.getSignatureStatuses([signature]).send();
3646
- if (status.value[0]?.confirmationStatus === "confirmed" || status.value[0]?.confirmationStatus === "finalized") {
3647
- return;
3648
- }
3649
- await new Promise((resolve) => setTimeout(resolve, 1e3));
709
+ const response = await fetch(`${this.config.marketplaceUrl}${path}`, {
710
+ ...options,
711
+ headers: {
712
+ ...headers,
713
+ ...options.headers
714
+ },
715
+ signal: controller.signal
716
+ });
717
+ return response;
718
+ } finally {
719
+ clearTimeout(timeoutId);
3650
720
  }
3651
- throw new Error("Transaction confirmation timeout");
3652
721
  }
3653
722
  };
3654
- function createH2AClient(options, wallet) {
3655
- return new H2AClient(options, wallet);
723
+ function createPayAIAgentSync(config = {}) {
724
+ return new PayAIAgentSync(config);
3656
725
  }
3657
726
 
3658
727
  // src/utils/test-ipfs-config.ts
@@ -3697,7 +766,7 @@ var IPFSOperationError = class extends Error {
3697
766
  this.name = "IPFSOperationError";
3698
767
  }
3699
768
  };
3700
- var DEFAULT_RETRY_CONFIG2 = {
769
+ var DEFAULT_RETRY_CONFIG = {
3701
770
  maxRetries: 3,
3702
771
  baseDelay: 1e3,
3703
772
  maxDelay: 3e4,
@@ -3758,7 +827,7 @@ var CircuitBreaker = class {
3758
827
  }
3759
828
  };
3760
829
  var RetryHandler = class {
3761
- constructor(config = DEFAULT_RETRY_CONFIG2) {
830
+ constructor(config = DEFAULT_RETRY_CONFIG) {
3762
831
  this.config = config;
3763
832
  this.circuitBreaker = new CircuitBreaker();
3764
833
  }
@@ -3883,7 +952,7 @@ var IPFSErrorHandler = class {
3883
952
  retryHandler;
3884
953
  fallbackHandler;
3885
954
  constructor(retryConfig) {
3886
- this.retryHandler = new RetryHandler({ ...DEFAULT_RETRY_CONFIG2, ...retryConfig });
955
+ this.retryHandler = new RetryHandler({ ...DEFAULT_RETRY_CONFIG, ...retryConfig });
3887
956
  this.fallbackHandler = new FallbackHandler();
3888
957
  }
3889
958
  async executeWithErrorHandling(operation, context, fallbackValue) {
@@ -4095,12 +1164,12 @@ function assembleStyles() {
4095
1164
  if (colorString.length === 3) {
4096
1165
  colorString = [...colorString].map((character) => character + character).join("");
4097
1166
  }
4098
- const integer7 = Number.parseInt(colorString, 16);
1167
+ const integer = Number.parseInt(colorString, 16);
4099
1168
  return [
4100
1169
  /* eslint-disable no-bitwise */
4101
- integer7 >> 16 & 255,
4102
- integer7 >> 8 & 255,
4103
- integer7 & 255
1170
+ integer >> 16 & 255,
1171
+ integer >> 8 & 255,
1172
+ integer & 255
4104
1173
  /* eslint-enable no-bitwise */
4105
1174
  ];
4106
1175
  },
@@ -4287,30 +1356,30 @@ var supports_color_default = supportsColor;
4287
1356
 
4288
1357
  // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
4289
1358
  function stringReplaceAll(string, substring, replacer) {
4290
- let index7 = string.indexOf(substring);
4291
- if (index7 === -1) {
1359
+ let index = string.indexOf(substring);
1360
+ if (index === -1) {
4292
1361
  return string;
4293
1362
  }
4294
1363
  const substringLength = substring.length;
4295
1364
  let endIndex = 0;
4296
1365
  let returnValue = "";
4297
1366
  do {
4298
- returnValue += string.slice(endIndex, index7) + substring + replacer;
4299
- endIndex = index7 + substringLength;
4300
- index7 = string.indexOf(substring, endIndex);
4301
- } while (index7 !== -1);
1367
+ returnValue += string.slice(endIndex, index) + substring + replacer;
1368
+ endIndex = index + substringLength;
1369
+ index = string.indexOf(substring, endIndex);
1370
+ } while (index !== -1);
4302
1371
  returnValue += string.slice(endIndex);
4303
1372
  return returnValue;
4304
1373
  }
4305
- function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index7) {
1374
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
4306
1375
  let endIndex = 0;
4307
1376
  let returnValue = "";
4308
1377
  do {
4309
- const gotCR = string[index7 - 1] === "\r";
4310
- returnValue += string.slice(endIndex, gotCR ? index7 - 1 : index7) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
4311
- endIndex = index7 + 1;
4312
- index7 = string.indexOf("\n", endIndex);
4313
- } while (index7 !== -1);
1378
+ const gotCR = string[index - 1] === "\r";
1379
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
1380
+ endIndex = index + 1;
1381
+ index = string.indexOf("\n", endIndex);
1382
+ } while (index !== -1);
4314
1383
  returnValue += string.slice(endIndex);
4315
1384
  return returnValue;
4316
1385
  }
@@ -4875,7 +1944,7 @@ var IPFSProvider = class {
4875
1944
  client;
4876
1945
  isPrivateNetwork;
4877
1946
  constructor(options) {
4878
- const createClient2 = __require("kubo-rpc-client").create;
1947
+ const createClient = __require("kubo-rpc-client").create;
4879
1948
  const ipfsNodeUrl = options?.ipfsNodeUrl || "http://localhost:5001";
4880
1949
  const headers = options?.headers || {};
4881
1950
  this.isPrivateNetwork = options?.usePrivateNetwork || false;
@@ -4890,7 +1959,7 @@ var IPFSProvider = class {
4890
1959
  if (typeof headers !== "object" || headers === null) {
4891
1960
  throw new Error("Headers must be a valid object");
4892
1961
  }
4893
- this.client = createClient2({
1962
+ this.client = createClient({
4894
1963
  url: ipfsNodeUrl,
4895
1964
  headers
4896
1965
  });
@@ -4922,9 +1991,9 @@ var IPFSProvider = class {
4922
1991
  * This is not foolproof but can catch obvious cases
4923
1992
  */
4924
1993
  isDataUnencrypted(data) {
4925
- const text7 = new TextDecoder("utf-8", { fatal: false }).decode(data.slice(0, 100));
1994
+ const text = new TextDecoder("utf-8", { fatal: false }).decode(data.slice(0, 100));
4926
1995
  const commonPatterns = ["{", "<", "BEGIN", "name", "address", "email", "password"];
4927
- return commonPatterns.some((pattern) => text7.toLowerCase().includes(pattern.toLowerCase()));
1996
+ return commonPatterns.some((pattern) => text.toLowerCase().includes(pattern.toLowerCase()));
4928
1997
  }
4929
1998
  async retrieve(hash) {
4930
1999
  try {
@@ -5277,6 +2346,6 @@ function clearFeatureGateCache() {
5277
2346
  featureCache.clear();
5278
2347
  }
5279
2348
 
5280
- export { A2AClient, AgentDiscoveryClient, CircuitBreaker, DEFAULT_RETRY_CONFIG2 as DEFAULT_RETRY_CONFIG, FEATURE_GATES, FallbackHandler, FetchWithPaymentClient, H2AClient, IPFSErrorHandler, IPFSOperationError, IPFSProvider, LocalStorageProvider, PaymentStreamingManager, PrivateDataQuery, PrivateMetadataStorage, RetryHandler, TEST_IPFS_CONFIG, WalletFundingService, X402AnalyticsTracker, X402Client, checkFeatureGate, clearFeatureGateCache, createA2AClient, createAgentDiscoveryClient, createH2AClient, createIPFSErrorHandler, createPrivacyManifest, createTestIPFSConfig, createX402AnalyticsTracker, createX402Client, createX402Middleware, defaultFundingService, ensureMinimumBalance, estimateStorageCost, fetchWithX402Payment, fundWallet, isIPFSError, withIPFSErrorHandling, withX402RateLimit, wrapFetchWithPayment, x402FastifyPlugin };
2349
+ export { CircuitBreaker, DEFAULT_RETRY_CONFIG, FEATURE_GATES, FallbackHandler, IPFSErrorHandler, IPFSOperationError, IPFSProvider, LocalStorageProvider, PayAIAgentSync, PayAIWebhookHandler, PrivateDataQuery, PrivateMetadataStorage, RetryHandler, TEST_IPFS_CONFIG, WalletFundingService, X402TransactionIndexer, checkFeatureGate, clearFeatureGateCache, createIPFSErrorHandler, createMockPayAIWebhook, createPayAIAgentSync, createPayAIWebhookHandler, createPrivacyManifest, createTestIPFSConfig, defaultFundingService, ensureMinimumBalance, estimateStorageCost, fundWallet, generateTestWebhookSignature, isIPFSError, withIPFSErrorHandling };
5281
2350
  //# sourceMappingURL=index.js.map
5282
2351
  //# sourceMappingURL=index.js.map