@agirails/sdk 2.0.1-beta → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +116 -108
- package/bin/actp +10 -0
- package/dist/ACTPClient.d.ts +456 -33
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +477 -93
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/AgentRegistry.json +782 -0
- package/dist/abi/EscrowVault.json +106 -38
- package/dist/abi/IdentityRegistry.json +316 -0
- package/dist/adapters/BaseAdapter.d.ts +231 -0
- package/dist/adapters/BaseAdapter.d.ts.map +1 -0
- package/dist/adapters/BaseAdapter.js +393 -0
- package/dist/adapters/BaseAdapter.js.map +1 -0
- package/dist/adapters/BeginnerAdapter.d.ts +152 -0
- package/dist/adapters/BeginnerAdapter.d.ts.map +1 -0
- package/dist/adapters/BeginnerAdapter.js +168 -0
- package/dist/adapters/BeginnerAdapter.js.map +1 -0
- package/dist/adapters/IntermediateAdapter.d.ts +211 -0
- package/dist/adapters/IntermediateAdapter.d.ts.map +1 -0
- package/dist/adapters/IntermediateAdapter.js +260 -0
- package/dist/adapters/IntermediateAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +15 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +26 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/builders/DeliveryProofBuilder.d.ts +60 -1
- package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
- package/dist/builders/DeliveryProofBuilder.js +81 -5
- package/dist/builders/DeliveryProofBuilder.js.map +1 -1
- package/dist/builders/QuoteBuilder.d.ts +101 -0
- package/dist/builders/QuoteBuilder.d.ts.map +1 -1
- package/dist/builders/QuoteBuilder.js +120 -3
- package/dist/builders/QuoteBuilder.js.map +1 -1
- package/dist/builders/index.d.ts +4 -0
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +4 -0
- package/dist/builders/index.js.map +1 -1
- package/dist/cli/commands/balance.d.ts +13 -0
- package/dist/cli/commands/balance.d.ts.map +1 -0
- package/dist/cli/commands/balance.js +89 -0
- package/dist/cli/commands/balance.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +24 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +424 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +192 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +143 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mint.d.ts +13 -0
- package/dist/cli/commands/mint.d.ts.map +1 -0
- package/dist/cli/commands/mint.js +91 -0
- package/dist/cli/commands/mint.js.map +1 -0
- package/dist/cli/commands/pay.d.ts +18 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +87 -0
- package/dist/cli/commands/pay.js.map +1 -0
- package/dist/cli/commands/simulate.d.ts +32 -0
- package/dist/cli/commands/simulate.d.ts.map +1 -0
- package/dist/cli/commands/simulate.js +290 -0
- package/dist/cli/commands/simulate.js.map +1 -0
- package/dist/cli/commands/time.d.ts +29 -0
- package/dist/cli/commands/time.d.ts.map +1 -0
- package/dist/cli/commands/time.js +252 -0
- package/dist/cli/commands/time.js.map +1 -0
- package/dist/cli/commands/tx.d.ts +16 -0
- package/dist/cli/commands/tx.d.ts.map +1 -0
- package/dist/cli/commands/tx.js +379 -0
- package/dist/cli/commands/tx.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +20 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +160 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +104 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/client.d.ts +70 -0
- package/dist/cli/utils/client.d.ts.map +1 -0
- package/dist/cli/utils/client.js +240 -0
- package/dist/cli/utils/client.js.map +1 -0
- package/dist/cli/utils/config.d.ts +91 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +240 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/output.d.ts +174 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +380 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/config/networks.d.ts +28 -0
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +60 -12
- package/dist/config/networks.js.map +1 -1
- package/dist/errors/index.d.ts +165 -2
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +260 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +61 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -36
- package/dist/index.js.map +1 -1
- package/dist/level0/Provider.d.ts +106 -0
- package/dist/level0/Provider.d.ts.map +1 -0
- package/dist/level0/Provider.js +10 -0
- package/dist/level0/Provider.js.map +1 -0
- package/dist/level0/ServiceDirectory.d.ts +74 -0
- package/dist/level0/ServiceDirectory.d.ts.map +1 -0
- package/dist/level0/ServiceDirectory.js +122 -0
- package/dist/level0/ServiceDirectory.js.map +1 -0
- package/dist/level0/index.d.ts +10 -0
- package/dist/level0/index.d.ts.map +1 -0
- package/dist/level0/index.js +15 -0
- package/dist/level0/index.js.map +1 -0
- package/dist/level0/provide.d.ts +51 -0
- package/dist/level0/provide.d.ts.map +1 -0
- package/dist/level0/provide.js +113 -0
- package/dist/level0/provide.js.map +1 -0
- package/dist/level0/request.d.ts +53 -0
- package/dist/level0/request.d.ts.map +1 -0
- package/dist/level0/request.js +462 -0
- package/dist/level0/request.js.map +1 -0
- package/dist/level1/Agent.d.ts +472 -0
- package/dist/level1/Agent.d.ts.map +1 -0
- package/dist/level1/Agent.js +1091 -0
- package/dist/level1/Agent.js.map +1 -0
- package/dist/level1/index.d.ts +10 -0
- package/dist/level1/index.d.ts.map +1 -0
- package/dist/level1/index.js +30 -0
- package/dist/level1/index.js.map +1 -0
- package/dist/level1/pricing/PriceCalculator.d.ts +62 -0
- package/dist/level1/pricing/PriceCalculator.d.ts.map +1 -0
- package/dist/level1/pricing/PriceCalculator.js +237 -0
- package/dist/level1/pricing/PriceCalculator.js.map +1 -0
- package/dist/level1/pricing/PricingStrategy.d.ts +179 -0
- package/dist/level1/pricing/PricingStrategy.d.ts.map +1 -0
- package/dist/level1/pricing/PricingStrategy.js +11 -0
- package/dist/level1/pricing/PricingStrategy.js.map +1 -0
- package/dist/level1/types/Job.d.ts +166 -0
- package/dist/level1/types/Job.d.ts.map +1 -0
- package/dist/level1/types/Job.js +11 -0
- package/dist/level1/types/Job.js.map +1 -0
- package/dist/level1/types/Options.d.ts +258 -0
- package/dist/level1/types/Options.d.ts.map +1 -0
- package/dist/level1/types/Options.js +8 -0
- package/dist/level1/types/Options.js.map +1 -0
- package/dist/level1/types/index.d.ts +8 -0
- package/dist/level1/types/index.d.ts.map +1 -0
- package/dist/level1/types/index.js +8 -0
- package/dist/level1/types/index.js.map +1 -0
- package/dist/protocol/ACTPKernel.d.ts +229 -2
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +367 -33
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/AgentRegistry.d.ts +177 -0
- package/dist/protocol/AgentRegistry.d.ts.map +1 -0
- package/dist/protocol/AgentRegistry.js +449 -0
- package/dist/protocol/AgentRegistry.js.map +1 -0
- package/dist/protocol/DIDManager.d.ts +289 -0
- package/dist/protocol/DIDManager.d.ts.map +1 -0
- package/dist/protocol/DIDManager.js +481 -0
- package/dist/protocol/DIDManager.js.map +1 -0
- package/dist/protocol/DIDResolver.d.ts +236 -0
- package/dist/protocol/DIDResolver.d.ts.map +1 -0
- package/dist/protocol/DIDResolver.js +495 -0
- package/dist/protocol/DIDResolver.js.map +1 -0
- package/dist/protocol/EASHelper.d.ts +57 -2
- package/dist/protocol/EASHelper.d.ts.map +1 -1
- package/dist/protocol/EASHelper.js +230 -37
- package/dist/protocol/EASHelper.js.map +1 -1
- package/dist/protocol/EscrowVault.d.ts +93 -2
- package/dist/protocol/EscrowVault.d.ts.map +1 -1
- package/dist/protocol/EscrowVault.js +122 -33
- package/dist/protocol/EscrowVault.js.map +1 -1
- package/dist/protocol/EventMonitor.d.ts +45 -1
- package/dist/protocol/EventMonitor.d.ts.map +1 -1
- package/dist/protocol/EventMonitor.js +64 -8
- package/dist/protocol/EventMonitor.js.map +1 -1
- package/dist/protocol/MessageSigner.d.ts +116 -2
- package/dist/protocol/MessageSigner.d.ts.map +1 -1
- package/dist/protocol/MessageSigner.js +215 -9
- package/dist/protocol/MessageSigner.js.map +1 -1
- package/dist/protocol/ProofGenerator.d.ts +93 -0
- package/dist/protocol/ProofGenerator.d.ts.map +1 -1
- package/dist/protocol/ProofGenerator.js +194 -9
- package/dist/protocol/ProofGenerator.js.map +1 -1
- package/dist/protocol/QuoteBuilder.d.ts +8 -0
- package/dist/protocol/QuoteBuilder.d.ts.map +1 -1
- package/dist/protocol/QuoteBuilder.js +8 -0
- package/dist/protocol/QuoteBuilder.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts +360 -0
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -0
- package/dist/runtime/BlockchainRuntime.js +767 -0
- package/dist/runtime/BlockchainRuntime.js.map +1 -0
- package/dist/runtime/IACTPRuntime.d.ts +271 -0
- package/dist/runtime/IACTPRuntime.d.ts.map +1 -0
- package/dist/runtime/IACTPRuntime.js +15 -0
- package/dist/runtime/IACTPRuntime.js.map +1 -0
- package/dist/runtime/MockRuntime.d.ts +445 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -0
- package/dist/runtime/MockRuntime.js +1065 -0
- package/dist/runtime/MockRuntime.js.map +1 -0
- package/dist/runtime/MockStateManager.d.ts +233 -0
- package/dist/runtime/MockStateManager.d.ts.map +1 -0
- package/dist/runtime/MockStateManager.js +533 -0
- package/dist/runtime/MockStateManager.js.map +1 -0
- package/dist/runtime/index.d.ts +14 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +42 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/types/MockState.d.ts +167 -0
- package/dist/runtime/types/MockState.d.ts.map +1 -0
- package/dist/runtime/types/MockState.js +43 -0
- package/dist/runtime/types/MockState.js.map +1 -0
- package/dist/types/agent.d.ts +76 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +8 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/did.d.ts +192 -0
- package/dist/types/did.d.ts.map +1 -0
- package/dist/types/did.js +38 -0
- package/dist/types/did.js.map +1 -0
- package/dist/types/eip712.d.ts +34 -0
- package/dist/types/eip712.d.ts.map +1 -1
- package/dist/types/eip712.js +31 -5
- package/dist/types/eip712.js.map +1 -1
- package/dist/types/escrow.d.ts +17 -10
- package/dist/types/escrow.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/message.d.ts +32 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +4 -0
- package/dist/types/message.js.map +1 -1
- package/dist/types/state.d.ts +28 -0
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/state.js +37 -6
- package/dist/types/state.js.map +1 -1
- package/dist/types/transaction.d.ts +17 -0
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/utils/ErrorRecoveryGuide.d.ts +125 -0
- package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -0
- package/dist/utils/ErrorRecoveryGuide.js +579 -0
- package/dist/utils/ErrorRecoveryGuide.js.map +1 -0
- package/dist/utils/Helpers.d.ts +453 -0
- package/dist/utils/Helpers.d.ts.map +1 -0
- package/dist/utils/Helpers.js +623 -0
- package/dist/utils/Helpers.js.map +1 -0
- package/dist/utils/IPFSClient.d.ts +113 -0
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +128 -7
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/Logger.d.ts +195 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +382 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/NonceManager.d.ts +234 -1
- package/dist/utils/NonceManager.d.ts.map +1 -1
- package/dist/utils/NonceManager.js +372 -7
- package/dist/utils/NonceManager.js.map +1 -1
- package/dist/utils/RateLimiter.d.ts +253 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +424 -0
- package/dist/utils/RateLimiter.js.map +1 -0
- package/dist/utils/ReceivedNonceTracker.d.ts +175 -0
- package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -1
- package/dist/utils/ReceivedNonceTracker.js +261 -5
- package/dist/utils/ReceivedNonceTracker.js.map +1 -1
- package/dist/utils/SDKLifecycle.d.ts +156 -0
- package/dist/utils/SDKLifecycle.d.ts.map +1 -0
- package/dist/utils/SDKLifecycle.js +347 -0
- package/dist/utils/SDKLifecycle.js.map +1 -0
- package/dist/utils/SecureNonce.d.ts +57 -0
- package/dist/utils/SecureNonce.d.ts.map +1 -0
- package/dist/utils/SecureNonce.js +80 -0
- package/dist/utils/SecureNonce.js.map +1 -0
- package/dist/utils/Semaphore.d.ts +123 -0
- package/dist/utils/Semaphore.d.ts.map +1 -0
- package/dist/utils/Semaphore.js +247 -0
- package/dist/utils/Semaphore.js.map +1 -0
- package/dist/utils/UsedAttestationTracker.d.ts +167 -0
- package/dist/utils/UsedAttestationTracker.d.ts.map +1 -0
- package/dist/utils/UsedAttestationTracker.js +309 -0
- package/dist/utils/UsedAttestationTracker.js.map +1 -0
- package/dist/utils/canonicalJson.d.ts +22 -0
- package/dist/utils/canonicalJson.d.ts.map +1 -1
- package/dist/utils/canonicalJson.js +26 -3
- package/dist/utils/canonicalJson.js.map +1 -1
- package/dist/utils/computeTypeHash.d.ts +14 -0
- package/dist/utils/computeTypeHash.d.ts.map +1 -1
- package/dist/utils/computeTypeHash.js +19 -2
- package/dist/utils/computeTypeHash.js.map +1 -1
- package/dist/utils/fsSafe.d.ts +14 -0
- package/dist/utils/fsSafe.d.ts.map +1 -0
- package/dist/utils/fsSafe.js +89 -0
- package/dist/utils/fsSafe.js.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +51 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/security.d.ts +147 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +391 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/validation.d.ts +40 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +184 -7
- package/dist/utils/validation.js.map +1 -1
- package/package.json +54 -37
- package/src/ACTPClient.ts +692 -178
- package/src/abi/AgentRegistry.json +782 -0
- package/src/abi/EscrowVault.json +106 -38
- package/src/abi/IdentityRegistry.json +316 -0
- package/src/adapters/BaseAdapter.ts +473 -0
- package/src/adapters/BeginnerAdapter.ts +232 -0
- package/src/adapters/IntermediateAdapter.ts +316 -0
- package/src/adapters/index.ts +25 -0
- package/src/builders/DeliveryProofBuilder.ts +3 -2
- package/src/cli/commands/balance.ts +110 -0
- package/src/cli/commands/batch.ts +487 -0
- package/src/cli/commands/config.ts +231 -0
- package/src/cli/commands/init.ts +161 -0
- package/src/cli/commands/mint.ts +116 -0
- package/src/cli/commands/pay.ts +113 -0
- package/src/cli/commands/simulate.ts +345 -0
- package/src/cli/commands/time.ts +303 -0
- package/src/cli/commands/tx.ts +448 -0
- package/src/cli/commands/watch.ts +211 -0
- package/src/cli/index.ts +116 -0
- package/src/cli/utils/client.ts +249 -0
- package/src/cli/utils/config.ts +282 -0
- package/src/cli/utils/output.ts +465 -0
- package/src/config/networks.ts +32 -9
- package/src/errors/index.ts +298 -1
- package/src/index.ts +207 -71
- package/src/level0/Provider.ts +117 -0
- package/src/level0/ServiceDirectory.ts +131 -0
- package/src/level0/index.ts +10 -0
- package/src/level0/provide.ts +131 -0
- package/src/level0/request.ts +494 -0
- package/src/level1/Agent.ts +1432 -0
- package/src/level1/index.ts +10 -0
- package/src/level1/pricing/PriceCalculator.ts +255 -0
- package/src/level1/pricing/PricingStrategy.ts +198 -0
- package/src/level1/types/Job.ts +179 -0
- package/src/level1/types/Options.ts +291 -0
- package/src/level1/types/index.ts +8 -0
- package/src/protocol/ACTPKernel.ts +175 -23
- package/src/protocol/AgentRegistry.ts +559 -0
- package/src/protocol/DIDManager.ts +629 -0
- package/src/protocol/DIDResolver.ts +554 -0
- package/src/protocol/EASHelper.ts +230 -46
- package/src/protocol/EscrowVault.ts +68 -50
- package/src/protocol/EventMonitor.ts +44 -15
- package/src/protocol/MessageSigner.ts +193 -13
- package/src/protocol/ProofGenerator.ts +223 -4
- package/src/runtime/BlockchainRuntime.ts +993 -0
- package/src/runtime/IACTPRuntime.ts +284 -0
- package/src/runtime/MockRuntime.ts +1244 -0
- package/src/runtime/MockStateManager.ts +576 -0
- package/src/runtime/index.ts +25 -0
- package/src/runtime/types/MockState.ts +227 -0
- package/src/types/agent.ts +79 -0
- package/src/types/did.ts +223 -0
- package/src/types/escrow.ts +12 -11
- package/src/types/index.ts +5 -1
- package/src/types/state.ts +12 -3
- package/src/types/transaction.ts +4 -1
- package/src/utils/ErrorRecoveryGuide.ts +675 -0
- package/src/utils/Helpers.ts +688 -0
- package/src/utils/IPFSClient.ts +122 -5
- package/src/utils/Logger.ts +484 -0
- package/src/utils/NonceManager.ts +305 -8
- package/src/utils/RateLimiter.ts +534 -0
- package/src/utils/ReceivedNonceTracker.ts +170 -0
- package/src/utils/SDKLifecycle.ts +416 -0
- package/src/utils/SecureNonce.ts +78 -0
- package/src/utils/Semaphore.ts +276 -0
- package/src/utils/UsedAttestationTracker.ts +387 -0
- package/src/utils/fsSafe.ts +75 -0
- package/src/utils/index.ts +80 -0
- package/src/utils/security.ts +418 -0
- package/src/utils/validation.ts +164 -0
- package/src/__tests__/ProofGenerator.test.ts +0 -124
- package/src/__tests__/QuoteBuilder.test.ts +0 -516
- package/src/__tests__/StateMachine.test.ts +0 -82
- package/src/__tests__/builders/DeliveryProofBuilder.test.ts +0 -581
- package/src/__tests__/integration/ACTPClient.test.ts +0 -263
- package/src/__tests__/integration.test.ts +0 -289
- package/src/__tests__/protocol/EASHelper.test.ts +0 -472
- package/src/__tests__/protocol/EventMonitor.test.ts +0 -382
- package/src/__tests__/security/ACTPKernel.security.test.ts +0 -1167
- package/src/__tests__/security/EscrowVault.security.test.ts +0 -570
- package/src/__tests__/security/MessageSigner.security.test.ts +0 -286
- package/src/__tests__/security/NonceReplay.security.test.ts +0 -501
- package/src/__tests__/security/validation.security.test.ts +0 -376
- package/src/__tests__/utils/IPFSClient.test.ts +0 -262
- package/src/__tests__/utils/NonceManager.test.ts +0 -205
- package/src/__tests__/utils/canonicalJson.test.ts +0 -153
package/src/ACTPClient.ts
CHANGED
|
@@ -1,276 +1,790 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
/**
|
|
2
|
+
* ACTPClient - Main entry point for AGIRAILS SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides the unified API for interacting with the ACTP protocol
|
|
5
|
+
* through three different abstraction levels:
|
|
6
|
+
* - `beginner`: High-level, opinionated API for simple use cases
|
|
7
|
+
* - `intermediate`: Balanced API with more control
|
|
8
|
+
* - `advanced`: Direct protocol access for full control
|
|
9
|
+
*
|
|
10
|
+
* @module ACTPClient
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Create client in mock mode
|
|
15
|
+
* const client = await ACTPClient.create({
|
|
16
|
+
* mode: 'mock',
|
|
17
|
+
* requesterAddress: '0x1234...',
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Beginner API - simplest approach
|
|
21
|
+
* const result = await client.beginner.pay({
|
|
22
|
+
* to: '0xProvider...',
|
|
23
|
+
* amount: '100',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Intermediate API - more control
|
|
27
|
+
* const txId = await client.intermediate.createTransaction({
|
|
28
|
+
* provider: '0xProvider...',
|
|
29
|
+
* amount: '100',
|
|
30
|
+
* });
|
|
31
|
+
* await client.intermediate.linkEscrow(txId);
|
|
32
|
+
*
|
|
33
|
+
* // Advanced API - direct protocol access
|
|
34
|
+
* const tx = await client.advanced.getTransaction(txId);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import * as path from 'path';
|
|
39
|
+
import * as os from 'os';
|
|
40
|
+
import * as fs from 'fs';
|
|
41
|
+
import { ethers } from 'ethers';
|
|
42
|
+
import { MockRuntime } from './runtime/MockRuntime';
|
|
43
|
+
import { MockStateManager } from './runtime/MockStateManager';
|
|
44
|
+
import { BlockchainRuntime } from './runtime/BlockchainRuntime';
|
|
45
|
+
import { IACTPRuntime, IMockRuntime } from './runtime/IACTPRuntime';
|
|
46
|
+
import { BeginnerAdapter } from './adapters/BeginnerAdapter';
|
|
47
|
+
import { IntermediateAdapter } from './adapters/IntermediateAdapter';
|
|
11
48
|
import { EASHelper, EASConfig } from './protocol/EASHelper';
|
|
12
|
-
import {
|
|
13
|
-
|
|
49
|
+
import { getNetwork } from './config/networks';
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Security: Path Validation
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validates that a state directory path is safe to use.
|
|
57
|
+
*
|
|
58
|
+
* SECURITY: Prevents path traversal attacks by ensuring:
|
|
59
|
+
* 1. No '..' components in the path
|
|
60
|
+
* 2. No symbolic links that could escape the intended directory
|
|
61
|
+
* 3. Path resolves to a location within home directory or current working directory
|
|
62
|
+
*
|
|
63
|
+
* @param stateDirectory - The directory path to validate
|
|
64
|
+
* @throws Error if path is unsafe
|
|
65
|
+
*/
|
|
66
|
+
function validateStateDirectory(stateDirectory: string): void {
|
|
67
|
+
// Check for path traversal characters
|
|
68
|
+
if (stateDirectory.includes('..')) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
'stateDirectory cannot contain path traversal characters (..). ' +
|
|
71
|
+
'Use absolute paths only for security.'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Resolve the path to get the absolute path
|
|
76
|
+
const resolvedPath = path.resolve(stateDirectory);
|
|
77
|
+
|
|
78
|
+
// If path exists, reject symlinks and use realpath for boundary checks.
|
|
79
|
+
// This blocks symlink escapes like "~/project" -> "/etc".
|
|
80
|
+
let effectivePath = resolvedPath;
|
|
81
|
+
if (fs.existsSync(resolvedPath)) {
|
|
82
|
+
const st = fs.lstatSync(resolvedPath);
|
|
83
|
+
if (st.isSymbolicLink()) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
'stateDirectory cannot be a symbolic link. ' +
|
|
86
|
+
`Path "${stateDirectory}" resolves to a symlink at "${resolvedPath}".`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (!st.isDirectory()) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`stateDirectory must be a directory. Path "${resolvedPath}" is not a directory.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
effectivePath = fs.realpathSync(resolvedPath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Get safe base directories
|
|
98
|
+
const homeDir = os.homedir();
|
|
99
|
+
const cwd = process.cwd();
|
|
100
|
+
|
|
101
|
+
// SECURITY FIX (C-5): Use path.relative() instead of startsWith()
|
|
102
|
+
// to handle case-insensitive filesystems (macOS, Windows) correctly.
|
|
103
|
+
// path.relative() returns a path starting with '..' if target is outside base.
|
|
104
|
+
const relativeToHome = path.relative(homeDir, effectivePath);
|
|
105
|
+
const relativeToCwd = path.relative(cwd, effectivePath);
|
|
106
|
+
|
|
107
|
+
// Check if path escapes the boundary (starts with '..' or is absolute)
|
|
108
|
+
const isUnderHome = !relativeToHome.startsWith('..') && !path.isAbsolute(relativeToHome);
|
|
109
|
+
const isUnderCwd = !relativeToCwd.startsWith('..') && !path.isAbsolute(relativeToCwd);
|
|
110
|
+
|
|
111
|
+
if (!isUnderHome && !isUnderCwd) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
'stateDirectory must be within home directory or current working directory. ' +
|
|
114
|
+
`Resolved path "${resolvedPath}" is outside allowed boundaries.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Additional check: Ensure path doesn't contain null bytes (can bypass validation)
|
|
119
|
+
if (stateDirectory.includes('\0')) {
|
|
120
|
+
throw new Error('stateDirectory contains invalid null byte character');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Type Guards
|
|
126
|
+
// ============================================================================
|
|
14
127
|
|
|
15
128
|
/**
|
|
16
|
-
*
|
|
129
|
+
* Type guard to check if runtime is MockRuntime.
|
|
130
|
+
*
|
|
131
|
+
* @param runtime - Runtime to check
|
|
132
|
+
* @returns True if runtime is IMockRuntime
|
|
133
|
+
*/
|
|
134
|
+
function isMockRuntime(runtime: IACTPRuntime): runtime is IMockRuntime {
|
|
135
|
+
return 'reset' in runtime && typeof (runtime as IMockRuntime).reset === 'function';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// Types
|
|
140
|
+
// ============================================================================
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Supported modes for ACTPClient.
|
|
144
|
+
*
|
|
145
|
+
* - `mock`: Local development mode with file-based state
|
|
146
|
+
* - `testnet`: Base Sepolia testnet (future)
|
|
147
|
+
* - `mainnet`: Base mainnet (future)
|
|
148
|
+
*/
|
|
149
|
+
export type ACTPClientMode = 'mock' | 'testnet' | 'mainnet';
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Configuration for creating an ACTPClient instance.
|
|
17
153
|
*/
|
|
18
154
|
export interface ACTPClientConfig {
|
|
19
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Operating mode.
|
|
157
|
+
*
|
|
158
|
+
* - 'mock': Local development with file-based state
|
|
159
|
+
* - 'testnet': Base Sepolia testnet
|
|
160
|
+
* - 'mainnet': Base mainnet
|
|
161
|
+
*/
|
|
162
|
+
mode: ACTPClientMode;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The requester's Ethereum address.
|
|
166
|
+
*
|
|
167
|
+
* This address is used as the "from" address for all transactions
|
|
168
|
+
* created through this client instance.
|
|
169
|
+
*
|
|
170
|
+
* @example '0x1111111111111111111111111111111111111111'
|
|
171
|
+
*/
|
|
172
|
+
requesterAddress: string;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Optional: Project root directory for mock state file storage.
|
|
176
|
+
*
|
|
177
|
+
* The state file will be stored at `{stateDirectory}/.actp/mock-state.json`.
|
|
178
|
+
* Defaults to current working directory.
|
|
179
|
+
* Only used when mode is 'mock'.
|
|
180
|
+
*/
|
|
181
|
+
stateDirectory?: string;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Optional: Private key for signing transactions.
|
|
185
|
+
*
|
|
186
|
+
* Required when mode is 'testnet' or 'mainnet'.
|
|
187
|
+
* Not used in 'mock' mode.
|
|
188
|
+
*
|
|
189
|
+
* ⚠️ CRITICAL SECURITY WARNING (C-1):
|
|
190
|
+
*
|
|
191
|
+
* **NEVER use raw private keys in production environments**
|
|
192
|
+
*
|
|
193
|
+
* **Recommended Approaches:**
|
|
194
|
+
* 1. **Encrypted JSON Keystore** (ethers.Wallet.fromEncryptedJson) - Best for server-side
|
|
195
|
+
* - Stores key encrypted with password
|
|
196
|
+
* - Requires decryption at runtime (password from secure vault)
|
|
197
|
+
* - Standard Web3 format (compatible with MetaMask, Geth, etc.)
|
|
198
|
+
*
|
|
199
|
+
* 2. **Hardware Wallets** (Ledger/Trezor) - Best for high-value operations
|
|
200
|
+
* - Private key never leaves device
|
|
201
|
+
* - User confirmation for each transaction
|
|
202
|
+
* - Future SDK integration planned
|
|
203
|
+
*
|
|
204
|
+
* 3. **KMS/HSM Integration** - Best for enterprise deployment
|
|
205
|
+
* - AWS KMS, Google Cloud KMS, Azure Key Vault
|
|
206
|
+
* - Private key never accessible to application
|
|
207
|
+
* - Audit trail for all signing operations
|
|
208
|
+
*
|
|
209
|
+
* **Security Requirements:**
|
|
210
|
+
* - NEVER log this value or include in error messages
|
|
211
|
+
* - NEVER store in plaintext files or git repositories
|
|
212
|
+
* - NEVER expose in API responses or client-side code
|
|
213
|
+
* - NEVER hardcode in source code (use environment variables minimum)
|
|
214
|
+
* - ALWAYS use encrypted storage (keystore, KMS, hardware wallet)
|
|
215
|
+
* - ALWAYS rotate keys if compromise suspected
|
|
216
|
+
* - The ACTPClient toJSON() method excludes this field from serialization
|
|
217
|
+
*
|
|
218
|
+
* **Example (Encrypted Keystore):**
|
|
219
|
+
* ```typescript
|
|
220
|
+
* import { Wallet } from 'ethers';
|
|
221
|
+
* import fs from 'fs';
|
|
222
|
+
*
|
|
223
|
+
* // Load encrypted keystore
|
|
224
|
+
* const keystore = fs.readFileSync('path/to/keystore.json', 'utf8');
|
|
225
|
+
* const password = process.env.KEYSTORE_PASSWORD; // From secure vault, not .env file
|
|
226
|
+
* const wallet = await Wallet.fromEncryptedJson(keystore, password);
|
|
227
|
+
*
|
|
228
|
+
* // Use with ACTPClient
|
|
229
|
+
* const client = await ACTPClient.create({
|
|
230
|
+
* mode: 'testnet',
|
|
231
|
+
* requesterAddress: wallet.address,
|
|
232
|
+
* privateKey: wallet.privateKey, // Decrypted at runtime only
|
|
233
|
+
* rpcUrl: process.env.RPC_URL
|
|
234
|
+
* });
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
20
237
|
privateKey?: string;
|
|
21
|
-
|
|
22
|
-
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Optional: RPC URL for blockchain connection.
|
|
241
|
+
*
|
|
242
|
+
* Required when mode is 'testnet' or 'mainnet'.
|
|
243
|
+
* Not used in 'mock' mode.
|
|
244
|
+
*
|
|
245
|
+
* @example 'https://base-sepolia.g.alchemy.com/v2/YOUR_KEY'
|
|
246
|
+
*/
|
|
23
247
|
rpcUrl?: string;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Optional: Contract address overrides.
|
|
251
|
+
*
|
|
252
|
+
* Override default deployed contract addresses.
|
|
253
|
+
* Used in 'testnet' and 'mainnet' modes.
|
|
254
|
+
*/
|
|
24
255
|
contracts?: {
|
|
25
256
|
actpKernel?: string;
|
|
26
257
|
escrowVault?: string;
|
|
27
258
|
usdc?: string;
|
|
28
259
|
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Optional: Gas settings for blockchain transactions.
|
|
263
|
+
*
|
|
264
|
+
* Used in 'testnet' and 'mainnet' modes.
|
|
265
|
+
*/
|
|
29
266
|
gasSettings?: {
|
|
30
267
|
maxFeePerGas?: bigint;
|
|
31
268
|
maxPriorityFeePerGas?: bigint;
|
|
32
269
|
};
|
|
33
|
-
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Optional: EAS (Ethereum Attestation Service) configuration.
|
|
273
|
+
*
|
|
274
|
+
* SECURITY FIX (C-4): Required for attestation verification in testnet/mainnet modes.
|
|
275
|
+
* If not provided, attestation verification in releaseEscrow() will be skipped.
|
|
276
|
+
*
|
|
277
|
+
* Used in 'testnet' and 'mainnet' modes.
|
|
278
|
+
*/
|
|
279
|
+
easConfig?: EASConfig;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Optional: Require valid EAS attestation before escrow release (blockchain modes).
|
|
283
|
+
*
|
|
284
|
+
* If true, `releaseEscrow()` will require an `attestationUID` and verify it on-chain via EAS.
|
|
285
|
+
*
|
|
286
|
+
* Default:
|
|
287
|
+
* - true when `easConfig` is provided
|
|
288
|
+
* - false otherwise
|
|
289
|
+
*/
|
|
290
|
+
requireAttestation?: boolean;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Optional: Custom runtime instance.
|
|
294
|
+
*
|
|
295
|
+
* For advanced use cases where you want to provide your own
|
|
296
|
+
* runtime implementation (e.g., for testing with custom mocks).
|
|
297
|
+
*
|
|
298
|
+
* If provided, mode and stateDirectory are ignored.
|
|
299
|
+
*/
|
|
300
|
+
runtime?: IACTPRuntime;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Result of creating an ACTPClient.
|
|
305
|
+
*
|
|
306
|
+
* Contains metadata about the client initialization.
|
|
307
|
+
*/
|
|
308
|
+
export interface ACTPClientInfo {
|
|
309
|
+
/** Operating mode */
|
|
310
|
+
mode: ACTPClientMode;
|
|
311
|
+
/** Requester address */
|
|
312
|
+
address: string;
|
|
313
|
+
/** State directory (mock mode only) */
|
|
314
|
+
stateDirectory?: string;
|
|
34
315
|
}
|
|
35
316
|
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// ACTPClient Class
|
|
319
|
+
// ============================================================================
|
|
320
|
+
|
|
36
321
|
/**
|
|
37
|
-
* ACTPClient - Main entry point for
|
|
322
|
+
* ACTPClient - Main entry point for AGIRAILS SDK.
|
|
323
|
+
*
|
|
324
|
+
* This class provides a unified interface to the ACTP protocol through
|
|
325
|
+
* three abstraction levels, catering to developers with different needs:
|
|
326
|
+
*
|
|
327
|
+
* **Beginner API** (`client.beginner`):
|
|
328
|
+
* - Simplest possible interface
|
|
329
|
+
* - Smart defaults (24h deadline, 2-day dispute window)
|
|
330
|
+
* - User-friendly inputs (strings, no BigInt)
|
|
331
|
+
* - Perfect for: Quick prototypes, simple integrations
|
|
38
332
|
*
|
|
39
|
-
*
|
|
333
|
+
* **Intermediate API** (`client.intermediate`):
|
|
334
|
+
* - Explicit lifecycle methods
|
|
335
|
+
* - More control over transaction flow
|
|
336
|
+
* - Still with user-friendly input parsing
|
|
337
|
+
* - Perfect for: Production apps needing control
|
|
338
|
+
*
|
|
339
|
+
* **Advanced API** (`client.advanced`):
|
|
340
|
+
* - Direct access to protocol runtime
|
|
341
|
+
* - Full control over all parameters
|
|
342
|
+
* - Protocol-level types (BigInt, timestamps)
|
|
343
|
+
* - Perfect for: Power users, custom integrations
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
40
346
|
* ```typescript
|
|
347
|
+
* // Create client
|
|
41
348
|
* const client = await ACTPClient.create({
|
|
42
|
-
*
|
|
43
|
-
*
|
|
349
|
+
* mode: 'mock',
|
|
350
|
+
* requesterAddress: '0xRequester...',
|
|
351
|
+
* });
|
|
352
|
+
*
|
|
353
|
+
* // Three ways to create a transaction:
|
|
354
|
+
*
|
|
355
|
+
* // 1. Beginner: One call does everything
|
|
356
|
+
* await client.beginner.pay({ to: '0xProvider', amount: '100' });
|
|
357
|
+
*
|
|
358
|
+
* // 2. Intermediate: Explicit steps
|
|
359
|
+
* const txId = await client.intermediate.createTransaction({
|
|
360
|
+
* provider: '0xProvider',
|
|
361
|
+
* amount: '100',
|
|
44
362
|
* });
|
|
363
|
+
* await client.intermediate.linkEscrow(txId);
|
|
45
364
|
*
|
|
46
|
-
*
|
|
365
|
+
* // 3. Advanced: Full control
|
|
366
|
+
* const txId = await client.advanced.createTransaction({
|
|
367
|
+
* provider: '0xProvider',
|
|
368
|
+
* requester: '0xRequester',
|
|
369
|
+
* amount: '100000000', // wei
|
|
370
|
+
* deadline: Math.floor(Date.now() / 1000) + 86400,
|
|
371
|
+
* disputeWindow: 172800,
|
|
372
|
+
* });
|
|
47
373
|
* ```
|
|
48
374
|
*/
|
|
49
375
|
export class ACTPClient {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
376
|
+
/**
|
|
377
|
+
* Beginner-level API.
|
|
378
|
+
*
|
|
379
|
+
* Provides the simplest interface for creating and checking transactions.
|
|
380
|
+
* Ideal for developers who want to "just make it work" without deep
|
|
381
|
+
* protocol knowledge.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```typescript
|
|
385
|
+
* const result = await client.beginner.pay({
|
|
386
|
+
* to: '0xProvider...',
|
|
387
|
+
* amount: '100',
|
|
388
|
+
* });
|
|
389
|
+
* console.log('Transaction ID:', result.txId);
|
|
390
|
+
* console.log('State:', result.state); // 'COMMITTED'
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
393
|
+
public readonly beginner: BeginnerAdapter;
|
|
63
394
|
|
|
64
395
|
/**
|
|
65
|
-
*
|
|
396
|
+
* Intermediate-level API.
|
|
397
|
+
*
|
|
398
|
+
* Provides explicit lifecycle methods for more control over
|
|
399
|
+
* the transaction flow while still offering user-friendly inputs.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* ```typescript
|
|
403
|
+
* // Create transaction (INITIATED state)
|
|
404
|
+
* const txId = await client.intermediate.createTransaction({
|
|
405
|
+
* provider: '0xProvider...',
|
|
406
|
+
* amount: '100',
|
|
407
|
+
* deadline: '+7d',
|
|
408
|
+
* });
|
|
409
|
+
*
|
|
410
|
+
* // Link escrow (auto-transitions to COMMITTED)
|
|
411
|
+
* await client.intermediate.linkEscrow(txId);
|
|
412
|
+
*
|
|
413
|
+
* // Transition to DELIVERED
|
|
414
|
+
* await client.intermediate.transitionState(txId, 'DELIVERED');
|
|
415
|
+
* ```
|
|
66
416
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
417
|
+
public readonly intermediate: IntermediateAdapter;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* The underlying runtime implementation.
|
|
421
|
+
*
|
|
422
|
+
* Direct access to the protocol runtime for advanced use cases.
|
|
423
|
+
* This is the same as `client.advanced`.
|
|
424
|
+
*/
|
|
425
|
+
public readonly runtime: IACTPRuntime;
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Client information (mode, address, etc.)
|
|
429
|
+
*/
|
|
430
|
+
public readonly info: ACTPClientInfo;
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* SECURITY FIX (C-4): EAS helper for attestation verification.
|
|
434
|
+
* Only available in testnet/mainnet modes when easConfig is provided.
|
|
435
|
+
*/
|
|
436
|
+
public readonly easHelper?: EASHelper;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Private constructor - use ACTPClient.create() factory method.
|
|
440
|
+
*/
|
|
441
|
+
private constructor(
|
|
442
|
+
runtime: IACTPRuntime,
|
|
443
|
+
requesterAddress: string,
|
|
444
|
+
info: ACTPClientInfo,
|
|
445
|
+
easHelper?: EASHelper
|
|
446
|
+
) {
|
|
447
|
+
this.runtime = runtime;
|
|
448
|
+
this.info = info;
|
|
449
|
+
this.easHelper = easHelper;
|
|
450
|
+
this.beginner = new BeginnerAdapter(runtime, requesterAddress, easHelper);
|
|
451
|
+
this.intermediate = new IntermediateAdapter(runtime, requesterAddress, easHelper);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// ==========================================================================
|
|
455
|
+
// Factory Method
|
|
456
|
+
// ==========================================================================
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Creates a new ACTPClient instance.
|
|
460
|
+
*
|
|
461
|
+
* This is the primary way to instantiate an ACTPClient.
|
|
462
|
+
* It handles runtime initialization based on the specified mode.
|
|
463
|
+
*
|
|
464
|
+
* @param config - Client configuration
|
|
465
|
+
* @returns Promise resolving to initialized ACTPClient
|
|
466
|
+
* @throws {Error} If mode is not supported (only 'mock' currently)
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```typescript
|
|
470
|
+
* // Mock mode (local development)
|
|
471
|
+
* const client = await ACTPClient.create({
|
|
472
|
+
* mode: 'mock',
|
|
473
|
+
* requesterAddress: '0x1234...',
|
|
474
|
+
* });
|
|
475
|
+
*
|
|
476
|
+
* // Mock mode with custom state directory
|
|
477
|
+
* const client = await ACTPClient.create({
|
|
478
|
+
* mode: 'mock',
|
|
479
|
+
* requesterAddress: '0x1234...',
|
|
480
|
+
* stateDirectory: '/custom/path/.actp',
|
|
481
|
+
* });
|
|
482
|
+
*
|
|
483
|
+
* // Custom runtime (for testing)
|
|
484
|
+
* const customRuntime = new MockRuntime();
|
|
485
|
+
* const client = await ACTPClient.create({
|
|
486
|
+
* mode: 'mock',
|
|
487
|
+
* requesterAddress: '0x1234...',
|
|
488
|
+
* runtime: customRuntime,
|
|
489
|
+
* });
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
492
|
+
static async create(config: ACTPClientConfig): Promise<ACTPClient> {
|
|
493
|
+
// Validate requester address
|
|
494
|
+
if (!config.requesterAddress) {
|
|
495
|
+
throw new Error('requesterAddress is required');
|
|
83
496
|
}
|
|
84
497
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
...this.networkConfig.gasSettings,
|
|
91
|
-
...config.gasSettings
|
|
92
|
-
}
|
|
93
|
-
};
|
|
498
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`Invalid requesterAddress: "${config.requesterAddress}". ` +
|
|
501
|
+
'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
|
|
502
|
+
);
|
|
94
503
|
}
|
|
95
504
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Object.freeze(this.networkConfig);
|
|
505
|
+
let runtime: IACTPRuntime;
|
|
506
|
+
let stateDirectory: string | undefined;
|
|
507
|
+
let easHelper: EASHelper | undefined;
|
|
100
508
|
|
|
101
|
-
//
|
|
102
|
-
if (config.
|
|
103
|
-
|
|
509
|
+
// If custom runtime provided, use it directly
|
|
510
|
+
if (config.runtime) {
|
|
511
|
+
runtime = config.runtime;
|
|
104
512
|
} else {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
513
|
+
// Initialize runtime based on mode
|
|
514
|
+
switch (config.mode) {
|
|
515
|
+
case 'mock': {
|
|
516
|
+
// SECURITY FIX: Enhanced path validation to prevent path traversal attacks
|
|
517
|
+
if (config.stateDirectory) {
|
|
518
|
+
validateStateDirectory(config.stateDirectory);
|
|
519
|
+
}
|
|
108
520
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// In ethers v6, getSigner() is async and returns a JsonRpcSigner
|
|
117
|
-
throw new ValidationError('signer', 'Either privateKey or signer must be provided');
|
|
118
|
-
}
|
|
521
|
+
// MockStateManager takes projectRoot as string parameter
|
|
522
|
+
const stateManager = new MockStateManager(config.stateDirectory);
|
|
523
|
+
runtime = new MockRuntime(stateManager);
|
|
524
|
+
stateDirectory = config.stateDirectory;
|
|
525
|
+
// EASHelper not needed in mock mode
|
|
526
|
+
break;
|
|
527
|
+
}
|
|
119
528
|
|
|
120
|
-
|
|
121
|
-
|
|
529
|
+
case 'testnet':
|
|
530
|
+
case 'mainnet': {
|
|
531
|
+
// Validate required parameters for blockchain modes
|
|
532
|
+
if (!config.privateKey) {
|
|
533
|
+
throw new Error(
|
|
534
|
+
`privateKey is required for ${config.mode} mode`
|
|
535
|
+
);
|
|
536
|
+
}
|
|
122
537
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// IPFS configuration could be added to ACTPClientConfig in the future
|
|
126
|
-
// For now, QuoteBuilder can work without IPFS (quotes stored only on-chain)
|
|
127
|
-
}
|
|
538
|
+
// Map mode to network config
|
|
539
|
+
const network = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
|
|
128
540
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.signer,
|
|
133
|
-
this.networkConfig.gasSettings
|
|
134
|
-
);
|
|
541
|
+
// Default RPC URL from network config if not provided
|
|
542
|
+
// This makes Level0/Agent usable on testnet without forcing users to pass rpcUrl explicitly.
|
|
543
|
+
const rpcUrl = config.rpcUrl ?? getNetwork(network).rpcUrl;
|
|
135
544
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
545
|
+
// Optional persistent state directory can be used for:
|
|
546
|
+
// - mock mode state (mock-state.json)
|
|
547
|
+
// - blockchain mode safety state (e.g., used-attestation replay protection)
|
|
548
|
+
if (config.stateDirectory) {
|
|
549
|
+
validateStateDirectory(config.stateDirectory);
|
|
550
|
+
}
|
|
141
551
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
552
|
+
// Create ethers provider and signer
|
|
553
|
+
const provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
554
|
+
const signer = new ethers.Wallet(config.privateKey, provider);
|
|
555
|
+
|
|
556
|
+
const requireAttestation = config.requireAttestation ?? Boolean(config.easConfig);
|
|
146
557
|
|
|
147
|
-
|
|
558
|
+
// Create BlockchainRuntime
|
|
559
|
+
const blockchainRuntime = new BlockchainRuntime({
|
|
560
|
+
network,
|
|
561
|
+
signer,
|
|
562
|
+
provider,
|
|
563
|
+
contracts: config.contracts,
|
|
564
|
+
gasSettings: config.gasSettings,
|
|
565
|
+
easConfig: config.easConfig,
|
|
566
|
+
requireAttestation,
|
|
567
|
+
stateDirectory: config.stateDirectory,
|
|
568
|
+
});
|
|
148
569
|
|
|
149
|
-
|
|
570
|
+
// Initialize async components
|
|
571
|
+
await blockchainRuntime.initialize();
|
|
150
572
|
|
|
151
|
-
|
|
152
|
-
this.quote = new QuoteBuilder(this.signer, this.nonceManager, this.ipfs);
|
|
573
|
+
runtime = blockchainRuntime;
|
|
153
574
|
|
|
154
|
-
|
|
155
|
-
|
|
575
|
+
// SECURITY FIX (C-4): Use the runtime's initialized EASHelper so
|
|
576
|
+
// adapters and runtime share the same tracker + verification logic.
|
|
577
|
+
if (config.easConfig) {
|
|
578
|
+
easHelper = blockchainRuntime.getEASHelper();
|
|
579
|
+
}
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
default:
|
|
584
|
+
throw new Error(
|
|
585
|
+
`Unknown mode: "${config.mode}". ` +
|
|
586
|
+
'Supported modes: "mock", "testnet", "mainnet"'
|
|
587
|
+
);
|
|
588
|
+
}
|
|
156
589
|
}
|
|
590
|
+
|
|
591
|
+
// Normalize address to lowercase for consistency
|
|
592
|
+
const normalizedAddress = config.requesterAddress.toLowerCase();
|
|
593
|
+
|
|
594
|
+
const info: ACTPClientInfo = {
|
|
595
|
+
mode: config.mode,
|
|
596
|
+
address: normalizedAddress,
|
|
597
|
+
stateDirectory,
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// SECURITY FIX (C-4): Pass EASHelper to adapters for attestation verification
|
|
601
|
+
return new ACTPClient(runtime, normalizedAddress, info, easHelper);
|
|
157
602
|
}
|
|
158
603
|
|
|
604
|
+
// ==========================================================================
|
|
605
|
+
// Public Methods
|
|
606
|
+
// ==========================================================================
|
|
607
|
+
|
|
159
608
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
609
|
+
* Advanced-level API.
|
|
610
|
+
*
|
|
611
|
+
* Provides direct access to the underlying protocol runtime.
|
|
612
|
+
* Use this when you need full control over all parameters.
|
|
613
|
+
*
|
|
614
|
+
* This is the same as accessing `client.runtime` directly.
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* ```typescript
|
|
618
|
+
* // Direct runtime access
|
|
619
|
+
* const txId = await client.advanced.createTransaction({
|
|
620
|
+
* provider: '0xProvider',
|
|
621
|
+
* requester: '0xRequester',
|
|
622
|
+
* amount: '100000000', // wei
|
|
623
|
+
* deadline: Math.floor(Date.now() / 1000) + 86400,
|
|
624
|
+
* });
|
|
625
|
+
*
|
|
626
|
+
* // Get transaction details
|
|
627
|
+
* const tx = await client.advanced.getTransaction(txId);
|
|
628
|
+
*
|
|
629
|
+
* // Time manipulation (mock mode only - requires IMockRuntime cast)
|
|
630
|
+
* import { IMockRuntime } from './runtime/IACTPRuntime';
|
|
631
|
+
* if (client.getMode() === 'mock') {
|
|
632
|
+
* (client.advanced as IMockRuntime).time.advanceTime(3600); // Advance 1 hour
|
|
633
|
+
* }
|
|
634
|
+
* ```
|
|
162
635
|
*/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
// Initialize EIP-712 domain for message signing
|
|
167
|
-
await client.messageSigner.initDomain(client.networkConfig.contracts.actpKernel);
|
|
168
|
-
|
|
169
|
-
return client;
|
|
636
|
+
get advanced(): IACTPRuntime {
|
|
637
|
+
return this.runtime;
|
|
170
638
|
}
|
|
171
639
|
|
|
172
640
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
641
|
+
* Gets the requester's Ethereum address.
|
|
642
|
+
*
|
|
643
|
+
* This is the address used as the "from" address for all transactions
|
|
644
|
+
* created through this client.
|
|
645
|
+
*
|
|
646
|
+
* @returns The requester's Ethereum address (normalized to lowercase)
|
|
647
|
+
*
|
|
648
|
+
* @example
|
|
649
|
+
* ```typescript
|
|
650
|
+
* const address = client.getAddress();
|
|
651
|
+
* console.log('My address:', address);
|
|
652
|
+
* // '0x1111111111111111111111111111111111111111'
|
|
653
|
+
* ```
|
|
175
654
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
655
|
+
getAddress(): string {
|
|
656
|
+
return this.info.address;
|
|
178
657
|
}
|
|
179
658
|
|
|
180
659
|
/**
|
|
181
|
-
*
|
|
660
|
+
* Gets the current operating mode.
|
|
661
|
+
*
|
|
662
|
+
* @returns The client's operating mode ('mock', 'testnet', or 'mainnet')
|
|
663
|
+
*
|
|
664
|
+
* @example
|
|
665
|
+
* ```typescript
|
|
666
|
+
* if (client.getMode() === 'mock') {
|
|
667
|
+
* console.log('Running in local development mode');
|
|
668
|
+
* }
|
|
669
|
+
* ```
|
|
182
670
|
*/
|
|
183
|
-
|
|
184
|
-
return
|
|
671
|
+
getMode(): ACTPClientMode {
|
|
672
|
+
return this.info.mode;
|
|
185
673
|
}
|
|
186
674
|
|
|
187
675
|
/**
|
|
188
|
-
*
|
|
676
|
+
* Resets the mock state to default.
|
|
677
|
+
*
|
|
678
|
+
* Only available in mock mode. Clears all transactions, escrows,
|
|
679
|
+
* and accounts, resetting to a fresh state.
|
|
680
|
+
*
|
|
681
|
+
* @throws {Error} If not in mock mode or runtime doesn't support reset
|
|
682
|
+
*
|
|
683
|
+
* @example
|
|
684
|
+
* ```typescript
|
|
685
|
+
* // Reset state between test runs
|
|
686
|
+
* await client.reset();
|
|
687
|
+
* ```
|
|
189
688
|
*/
|
|
190
|
-
|
|
191
|
-
|
|
689
|
+
async reset(): Promise<void> {
|
|
690
|
+
if (this.info.mode !== 'mock') {
|
|
691
|
+
throw new Error(
|
|
692
|
+
`reset() is only available in mock mode. Current mode: "${this.info.mode}"`
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
if (!isMockRuntime(this.runtime)) {
|
|
697
|
+
throw new Error('Runtime does not support reset operation');
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
await this.runtime.reset();
|
|
192
701
|
}
|
|
193
702
|
|
|
194
703
|
/**
|
|
195
|
-
*
|
|
704
|
+
* Custom JSON serialization to prevent private key exposure.
|
|
705
|
+
*
|
|
706
|
+
* SECURITY FIX (HIGH-4): Prevents accidental private key logging
|
|
707
|
+
* when ACTPClient instance is serialized (e.g., JSON.stringify, console.log).
|
|
708
|
+
*
|
|
709
|
+
* @returns Safe serializable object with sensitive data removed
|
|
196
710
|
*/
|
|
197
|
-
|
|
198
|
-
return
|
|
711
|
+
toJSON(): object {
|
|
712
|
+
return {
|
|
713
|
+
mode: this.info.mode,
|
|
714
|
+
address: this.info.address,
|
|
715
|
+
stateDirectory: this.info.stateDirectory,
|
|
716
|
+
isInitialized: true,
|
|
717
|
+
// Explicitly exclude: privateKey, signer, provider internals
|
|
718
|
+
_warning: 'Sensitive data (privateKey, signer) excluded for security',
|
|
719
|
+
};
|
|
199
720
|
}
|
|
200
721
|
|
|
201
722
|
/**
|
|
202
|
-
*
|
|
723
|
+
* Custom string representation for debugging.
|
|
724
|
+
*
|
|
725
|
+
* SECURITY FIX (HIGH-4): Prevents private key exposure in logs.
|
|
203
726
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return await this.provider.getBlockNumber();
|
|
207
|
-
} catch (error: any) {
|
|
208
|
-
throw new NetworkError(this.networkConfig.name, error.message);
|
|
209
|
-
}
|
|
727
|
+
toString(): string {
|
|
728
|
+
return `ACTPClient(mode=${this.info.mode}, address=${this.info.address})`;
|
|
210
729
|
}
|
|
211
730
|
|
|
212
731
|
/**
|
|
213
|
-
*
|
|
732
|
+
* Custom inspect for Node.js util.inspect (console.log).
|
|
733
|
+
*
|
|
734
|
+
* SECURITY FIX (HIGH-4): Prevents private key exposure in console output.
|
|
214
735
|
*/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const feeData = await this.provider.getFeeData();
|
|
218
|
-
return feeData.gasPrice || 0n;
|
|
219
|
-
} catch (error: any) {
|
|
220
|
-
throw new NetworkError(this.networkConfig.name, error.message);
|
|
221
|
-
}
|
|
736
|
+
[Symbol.for('nodejs.util.inspect.custom')](): string {
|
|
737
|
+
return this.toString();
|
|
222
738
|
}
|
|
223
739
|
|
|
224
740
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* SECURITY: This method verifies the attestation belongs to the transaction BEFORE
|
|
228
|
-
* releasing escrow. This protects against malicious providers submitting attestations
|
|
229
|
-
* from different transactions.
|
|
741
|
+
* Mints USDC tokens to an address.
|
|
230
742
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
743
|
+
* Only available in mock mode. Useful for testing scenarios
|
|
744
|
+
* where you need to fund accounts.
|
|
233
745
|
*
|
|
234
|
-
* @param
|
|
235
|
-
* @param
|
|
236
|
-
* @throws {Error} If
|
|
237
|
-
* @throws {Error} If attestation verification fails (revoked, expired, or txId mismatch)
|
|
238
|
-
* @throws {TransactionRevertedError} If escrow release fails
|
|
746
|
+
* @param address - Address to mint tokens to
|
|
747
|
+
* @param amount - Amount to mint (in USDC wei, e.g., '1000000' for 1 USDC)
|
|
748
|
+
* @throws {Error} If not in mock mode or runtime doesn't support mintTokens
|
|
239
749
|
*
|
|
240
750
|
* @example
|
|
241
751
|
* ```typescript
|
|
242
|
-
* //
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* // Verify and release escrow in one call
|
|
246
|
-
* await client.releaseEscrowWithVerification(txId, tx.attestationUID);
|
|
752
|
+
* // Mint 1000 USDC to the requester
|
|
753
|
+
* await client.mintTokens(client.getAddress(), '1000000000'); // 1000 * 10^6
|
|
247
754
|
* ```
|
|
248
755
|
*/
|
|
249
|
-
async
|
|
250
|
-
|
|
251
|
-
if (!this.eas) {
|
|
756
|
+
async mintTokens(address: string, amount: string): Promise<void> {
|
|
757
|
+
if (this.info.mode !== 'mock') {
|
|
252
758
|
throw new Error(
|
|
253
|
-
|
|
759
|
+
`mintTokens() is only available in mock mode. Current mode: "${this.info.mode}"`
|
|
254
760
|
);
|
|
255
761
|
}
|
|
256
762
|
|
|
257
|
-
|
|
258
|
-
|
|
763
|
+
if (!isMockRuntime(this.runtime)) {
|
|
764
|
+
throw new Error('Runtime does not support mintTokens operation');
|
|
765
|
+
}
|
|
259
766
|
|
|
260
|
-
|
|
261
|
-
await this.kernel.releaseEscrow(txId);
|
|
767
|
+
await this.runtime.mintTokens(address, amount);
|
|
262
768
|
}
|
|
263
769
|
|
|
264
770
|
/**
|
|
265
|
-
*
|
|
771
|
+
* Gets the USDC balance of an address.
|
|
772
|
+
*
|
|
773
|
+
* @param address - Address to check balance for
|
|
774
|
+
* @returns Promise resolving to balance in USDC wei
|
|
775
|
+
* @throws {Error} If runtime doesn't support getBalance
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* ```typescript
|
|
779
|
+
* const balance = await client.getBalance(client.getAddress());
|
|
780
|
+
* console.log('Balance:', balance); // '1000000000' (1000 USDC)
|
|
781
|
+
* ```
|
|
266
782
|
*/
|
|
267
|
-
|
|
268
|
-
if (!
|
|
269
|
-
throw new
|
|
783
|
+
async getBalance(address: string): Promise<string> {
|
|
784
|
+
if (!isMockRuntime(this.runtime)) {
|
|
785
|
+
throw new Error('Runtime does not support getBalance operation');
|
|
270
786
|
}
|
|
271
787
|
|
|
272
|
-
|
|
273
|
-
throw new ValidationError('auth', 'Provide either privateKey, signer, or provider with signer access');
|
|
274
|
-
}
|
|
788
|
+
return this.runtime.getBalance(address);
|
|
275
789
|
}
|
|
276
790
|
}
|