@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
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulate Command - Dry-run commands without executing
|
|
3
|
+
*
|
|
4
|
+
* Agent-first feature: Preview what a command would do
|
|
5
|
+
* without actually executing it. Perfect for:
|
|
6
|
+
* - Testing scripts before running on mainnet
|
|
7
|
+
* - Understanding fee calculations
|
|
8
|
+
* - Validating input parameters
|
|
9
|
+
*
|
|
10
|
+
* @module cli/commands/simulate
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { Output, ExitCode, fmt } from '../utils/output';
|
|
15
|
+
import { loadConfig } from '../utils/config';
|
|
16
|
+
import { mapError } from '../utils/client';
|
|
17
|
+
import { BaseAdapter, ValidationError, MIN_AMOUNT_WEI } from '../../adapters/BaseAdapter';
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Command Definition
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
export function createSimulateCommand(): Command {
|
|
24
|
+
const cmd = new Command('simulate')
|
|
25
|
+
.description('Dry-run a command without executing (agent-first feature)');
|
|
26
|
+
|
|
27
|
+
cmd.addCommand(createSimulatePayCommand());
|
|
28
|
+
cmd.addCommand(createSimulateFeeCommand());
|
|
29
|
+
|
|
30
|
+
return cmd;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// simulate pay
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
function createSimulatePayCommand(): Command {
|
|
38
|
+
return new Command('pay')
|
|
39
|
+
.description('Simulate a payment transaction')
|
|
40
|
+
.argument('<to>', 'Provider address')
|
|
41
|
+
.argument('<amount>', 'Amount to pay')
|
|
42
|
+
.option('-d, --deadline <deadline>', 'Deadline (+24h, +7d, or Unix timestamp)', '+24h')
|
|
43
|
+
.option('--json', 'Output as JSON')
|
|
44
|
+
.action(async (to, amount, options) => {
|
|
45
|
+
const output = new Output(options.json ? 'json' : 'human');
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
await runSimulatePay(to, amount, options, output);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
const structuredError = mapError(error);
|
|
51
|
+
output.errorResult({
|
|
52
|
+
code: structuredError.code,
|
|
53
|
+
message: structuredError.message,
|
|
54
|
+
});
|
|
55
|
+
process.exit(ExitCode.ERROR);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface SimulatePayOptions {
|
|
61
|
+
deadline: string;
|
|
62
|
+
json?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function runSimulatePay(
|
|
66
|
+
to: string,
|
|
67
|
+
amount: string,
|
|
68
|
+
options: SimulatePayOptions,
|
|
69
|
+
output: Output
|
|
70
|
+
): Promise<void> {
|
|
71
|
+
const config = loadConfig();
|
|
72
|
+
|
|
73
|
+
// Create a mock adapter just for parsing
|
|
74
|
+
const adapter = new SimulationAdapter(config.address);
|
|
75
|
+
|
|
76
|
+
// Validate and parse inputs
|
|
77
|
+
const validation = adapter.validatePayment(to, amount, options.deadline);
|
|
78
|
+
|
|
79
|
+
if (!validation.valid) {
|
|
80
|
+
output.result({
|
|
81
|
+
valid: false,
|
|
82
|
+
errors: validation.errors,
|
|
83
|
+
});
|
|
84
|
+
process.exit(ExitCode.INVALID_INPUT);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Calculate fee
|
|
88
|
+
const amountWei = validation.parsedAmount!;
|
|
89
|
+
const feeCalculation = calculateFee(amountWei);
|
|
90
|
+
|
|
91
|
+
const result = {
|
|
92
|
+
valid: true,
|
|
93
|
+
simulation: {
|
|
94
|
+
action: 'CREATE_AND_FUND_TRANSACTION',
|
|
95
|
+
provider: to.toLowerCase(),
|
|
96
|
+
requester: config.address.toLowerCase(),
|
|
97
|
+
amount: formatUsdc(amountWei.toString()) + ' USDC',
|
|
98
|
+
amountWei: amountWei.toString(),
|
|
99
|
+
deadline: new Date(validation.parsedDeadline! * 1000).toISOString(),
|
|
100
|
+
deadlineUnix: validation.parsedDeadline,
|
|
101
|
+
},
|
|
102
|
+
fees: {
|
|
103
|
+
platformFee: formatUsdc(feeCalculation.fee.toString()) + ' USDC',
|
|
104
|
+
platformFeeWei: feeCalculation.fee.toString(),
|
|
105
|
+
feeRate: feeCalculation.effectiveRate,
|
|
106
|
+
providerReceives: formatUsdc(feeCalculation.providerReceives.toString()) + ' USDC',
|
|
107
|
+
minimumApplied: feeCalculation.minimumApplied,
|
|
108
|
+
},
|
|
109
|
+
requirements: {
|
|
110
|
+
requiredBalance: formatUsdc((amountWei + feeCalculation.fee).toString()) + ' USDC',
|
|
111
|
+
mode: config.mode,
|
|
112
|
+
},
|
|
113
|
+
warnings: validation.warnings,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (options.json) {
|
|
117
|
+
output.result(result);
|
|
118
|
+
} else {
|
|
119
|
+
output.section('Simulation Results');
|
|
120
|
+
output.print('');
|
|
121
|
+
output.print(fmt.bold('Transaction Details:'));
|
|
122
|
+
output.keyValue(' Action', 'Create and fund transaction');
|
|
123
|
+
output.keyValue(' Provider', to);
|
|
124
|
+
output.keyValue(' Amount', result.simulation.amount);
|
|
125
|
+
output.keyValue(' Deadline', result.simulation.deadline);
|
|
126
|
+
output.print('');
|
|
127
|
+
output.print(fmt.bold('Fee Breakdown (1% + $0.05 min):'));
|
|
128
|
+
output.keyValue(' Platform Fee', result.fees.platformFee);
|
|
129
|
+
output.keyValue(' Effective Rate', result.fees.feeRate);
|
|
130
|
+
output.keyValue(' Provider Receives', result.fees.providerReceives);
|
|
131
|
+
if (feeCalculation.minimumApplied) {
|
|
132
|
+
output.print(fmt.yellow(' (Minimum fee applied - amount < $5)'));
|
|
133
|
+
}
|
|
134
|
+
output.print('');
|
|
135
|
+
output.print(fmt.bold('Requirements:'));
|
|
136
|
+
output.keyValue(' Required Balance', result.requirements.requiredBalance);
|
|
137
|
+
output.keyValue(' Mode', result.requirements.mode);
|
|
138
|
+
|
|
139
|
+
if (validation.warnings && validation.warnings.length > 0) {
|
|
140
|
+
output.print('');
|
|
141
|
+
output.print(fmt.yellow('Warnings:'));
|
|
142
|
+
for (const warning of validation.warnings) {
|
|
143
|
+
output.print(fmt.yellow(` - ${warning}`));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
output.print('');
|
|
148
|
+
output.success('Simulation complete - no transaction created');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// simulate fee
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
function createSimulateFeeCommand(): Command {
|
|
157
|
+
return new Command('fee')
|
|
158
|
+
.description('Calculate fee for a given amount')
|
|
159
|
+
.argument('<amount>', 'Amount to calculate fee for')
|
|
160
|
+
.option('--json', 'Output as JSON')
|
|
161
|
+
.action(async (amount, options) => {
|
|
162
|
+
const output = new Output(options.json ? 'json' : 'human');
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
// Parse amount
|
|
166
|
+
const adapter = new SimulationAdapter('0x0000000000000000000000000000000000000000');
|
|
167
|
+
const parsedAmount = adapter.parseAmountPublic(amount);
|
|
168
|
+
|
|
169
|
+
const feeCalc = calculateFee(parsedAmount);
|
|
170
|
+
|
|
171
|
+
const result = {
|
|
172
|
+
amount: formatUsdc(parsedAmount.toString()) + ' USDC',
|
|
173
|
+
amountWei: parsedAmount.toString(),
|
|
174
|
+
fee: formatUsdc(feeCalc.fee.toString()) + ' USDC',
|
|
175
|
+
feeWei: feeCalc.fee.toString(),
|
|
176
|
+
effectiveRate: feeCalc.effectiveRate,
|
|
177
|
+
providerReceives: formatUsdc(feeCalc.providerReceives.toString()) + ' USDC',
|
|
178
|
+
totalRequired: formatUsdc((parsedAmount + feeCalc.fee).toString()) + ' USDC',
|
|
179
|
+
minimumApplied: feeCalc.minimumApplied,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
if (options.json) {
|
|
183
|
+
output.result(result);
|
|
184
|
+
} else {
|
|
185
|
+
output.section('Fee Calculation');
|
|
186
|
+
output.keyValue('Amount', result.amount);
|
|
187
|
+
output.keyValue('Platform Fee', result.fee);
|
|
188
|
+
output.keyValue('Effective Rate', result.effectiveRate);
|
|
189
|
+
output.keyValue('Provider Receives', result.providerReceives);
|
|
190
|
+
output.keyValue('Total Required', result.totalRequired);
|
|
191
|
+
if (feeCalc.minimumApplied) {
|
|
192
|
+
output.print('');
|
|
193
|
+
output.info('Minimum fee ($0.05) applied because amount < $5');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
const structuredError = mapError(error);
|
|
198
|
+
output.errorResult({
|
|
199
|
+
code: structuredError.code,
|
|
200
|
+
message: structuredError.message,
|
|
201
|
+
});
|
|
202
|
+
process.exit(ExitCode.ERROR);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ============================================================================
|
|
208
|
+
// Helpers
|
|
209
|
+
// ============================================================================
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Extended adapter for simulation purposes
|
|
213
|
+
*/
|
|
214
|
+
class SimulationAdapter extends BaseAdapter {
|
|
215
|
+
constructor(requesterAddress: string) {
|
|
216
|
+
super(requesterAddress);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Validate payment parameters without executing
|
|
221
|
+
*/
|
|
222
|
+
validatePayment(
|
|
223
|
+
to: string,
|
|
224
|
+
amount: string | number,
|
|
225
|
+
deadline?: string | number
|
|
226
|
+
): {
|
|
227
|
+
valid: boolean;
|
|
228
|
+
errors: string[];
|
|
229
|
+
warnings: string[];
|
|
230
|
+
parsedAmount?: bigint;
|
|
231
|
+
parsedDeadline?: number;
|
|
232
|
+
} {
|
|
233
|
+
const errors: string[] = [];
|
|
234
|
+
const warnings: string[] = [];
|
|
235
|
+
let parsedAmount: bigint | undefined;
|
|
236
|
+
let parsedDeadline: number | undefined;
|
|
237
|
+
|
|
238
|
+
// Validate address
|
|
239
|
+
try {
|
|
240
|
+
this.validateAddress(to, 'to');
|
|
241
|
+
} catch (e) {
|
|
242
|
+
errors.push((e as Error).message);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Validate amount
|
|
246
|
+
try {
|
|
247
|
+
parsedAmount = this.parseAmount(amount);
|
|
248
|
+
|
|
249
|
+
// Check for small amount warning
|
|
250
|
+
if (parsedAmount < 5_000_000n) {
|
|
251
|
+
// Less than $5
|
|
252
|
+
warnings.push('Amount is below $5 - minimum fee ($0.05) will apply');
|
|
253
|
+
}
|
|
254
|
+
} catch (e) {
|
|
255
|
+
errors.push((e as Error).message);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Validate deadline
|
|
259
|
+
try {
|
|
260
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
261
|
+
parsedDeadline = this.parseDeadline(deadline, currentTime);
|
|
262
|
+
|
|
263
|
+
if (parsedDeadline <= currentTime) {
|
|
264
|
+
errors.push('Deadline must be in the future');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Check for short deadline warning
|
|
268
|
+
const hoursUntilDeadline = (parsedDeadline - currentTime) / 3600;
|
|
269
|
+
if (hoursUntilDeadline < 1) {
|
|
270
|
+
warnings.push('Deadline is less than 1 hour from now');
|
|
271
|
+
}
|
|
272
|
+
} catch (e) {
|
|
273
|
+
errors.push((e as Error).message);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Check self-payment
|
|
277
|
+
if (to.toLowerCase() === this.requesterAddress.toLowerCase()) {
|
|
278
|
+
errors.push('Cannot pay yourself');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
valid: errors.length === 0,
|
|
283
|
+
errors,
|
|
284
|
+
warnings,
|
|
285
|
+
parsedAmount,
|
|
286
|
+
parsedDeadline,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Public access to parseAmount for fee calculation
|
|
292
|
+
*/
|
|
293
|
+
parseAmountPublic(amount: string | number): bigint {
|
|
294
|
+
return this.parseAmount(amount);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Calculate platform fee based on AGIRAILS fee model:
|
|
300
|
+
* - 1% of transaction amount
|
|
301
|
+
* - $0.05 minimum
|
|
302
|
+
*/
|
|
303
|
+
function calculateFee(amountWei: bigint): {
|
|
304
|
+
fee: bigint;
|
|
305
|
+
providerReceives: bigint;
|
|
306
|
+
effectiveRate: string;
|
|
307
|
+
minimumApplied: boolean;
|
|
308
|
+
} {
|
|
309
|
+
// 1% fee
|
|
310
|
+
const percentFee = amountWei / 100n;
|
|
311
|
+
|
|
312
|
+
// $0.05 minimum in wei (6 decimals)
|
|
313
|
+
const minimumFeeWei = 50_000n;
|
|
314
|
+
|
|
315
|
+
// Apply minimum
|
|
316
|
+
const fee = percentFee > minimumFeeWei ? percentFee : minimumFeeWei;
|
|
317
|
+
const minimumApplied = percentFee < minimumFeeWei;
|
|
318
|
+
|
|
319
|
+
// Calculate what provider receives (amount minus fee)
|
|
320
|
+
const providerReceives = amountWei - fee;
|
|
321
|
+
|
|
322
|
+
// Calculate effective rate
|
|
323
|
+
const effectiveRatePercent = (Number(fee) / Number(amountWei)) * 100;
|
|
324
|
+
const effectiveRate = effectiveRatePercent.toFixed(2) + '%';
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
fee,
|
|
328
|
+
providerReceives,
|
|
329
|
+
effectiveRate,
|
|
330
|
+
minimumApplied,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Format USDC amount from wei to decimal
|
|
336
|
+
*/
|
|
337
|
+
function formatUsdc(weiAmount: string): string {
|
|
338
|
+
const amount = BigInt(weiAmount);
|
|
339
|
+
const whole = amount / 1_000_000n;
|
|
340
|
+
const decimal = amount % 1_000_000n;
|
|
341
|
+
const decimalStr = decimal.toString().padStart(6, '0').slice(0, 2);
|
|
342
|
+
return `${whole}.${decimalStr}`;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export { runSimulatePay, calculateFee };
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time Command - Manipulate mock blockchain time
|
|
3
|
+
*
|
|
4
|
+
* Mock mode only feature for testing time-dependent logic:
|
|
5
|
+
* - Deadline expiration
|
|
6
|
+
* - Dispute window progression
|
|
7
|
+
* - Time-based state transitions
|
|
8
|
+
*
|
|
9
|
+
* @module cli/commands/time
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import { Output, ExitCode, fmt } from '../utils/output';
|
|
14
|
+
import { loadConfig } from '../utils/config';
|
|
15
|
+
import { createClient, mapError } from '../utils/client';
|
|
16
|
+
import { MockRuntime } from '../../runtime/MockRuntime';
|
|
17
|
+
import { IMockRuntime } from '../../runtime/IACTPRuntime';
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Command Definition
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
export function createTimeCommand(): Command {
|
|
24
|
+
const cmd = new Command('time')
|
|
25
|
+
.description('Manipulate mock blockchain time (mock mode only)');
|
|
26
|
+
|
|
27
|
+
cmd.addCommand(createTimeShowCommand());
|
|
28
|
+
cmd.addCommand(createTimeAdvanceCommand());
|
|
29
|
+
cmd.addCommand(createTimeSetCommand());
|
|
30
|
+
|
|
31
|
+
return cmd;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// time show
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
function createTimeShowCommand(): Command {
|
|
39
|
+
return new Command('show')
|
|
40
|
+
.description('Show current mock blockchain time')
|
|
41
|
+
.option('--json', 'Output as JSON')
|
|
42
|
+
.option('-q, --quiet', 'Output only the timestamp')
|
|
43
|
+
.action(async (options) => {
|
|
44
|
+
const output = new Output(
|
|
45
|
+
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
validateMockMode();
|
|
50
|
+
|
|
51
|
+
const client = await createClient();
|
|
52
|
+
const runtime = client.runtime as IMockRuntime;
|
|
53
|
+
const currentTime = runtime.time.now();
|
|
54
|
+
|
|
55
|
+
if (options.quiet) {
|
|
56
|
+
console.log(currentTime);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
output.result({
|
|
61
|
+
timestamp: currentTime,
|
|
62
|
+
iso: new Date(currentTime * 1000).toISOString(),
|
|
63
|
+
readable: formatRelativeTime(currentTime),
|
|
64
|
+
});
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const structuredError = mapError(error);
|
|
67
|
+
output.errorResult({
|
|
68
|
+
code: structuredError.code,
|
|
69
|
+
message: structuredError.message,
|
|
70
|
+
});
|
|
71
|
+
process.exit(ExitCode.ERROR);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// time advance
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
function createTimeAdvanceCommand(): Command {
|
|
81
|
+
return new Command('advance')
|
|
82
|
+
.description('Advance mock blockchain time')
|
|
83
|
+
.argument('<duration>', 'Duration to advance (e.g., "1h", "30m", "7d", "3600")')
|
|
84
|
+
.option('--json', 'Output as JSON')
|
|
85
|
+
.option('-q, --quiet', 'Minimal output')
|
|
86
|
+
.action(async (duration, options) => {
|
|
87
|
+
const output = new Output(
|
|
88
|
+
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
validateMockMode();
|
|
93
|
+
|
|
94
|
+
const seconds = parseDuration(duration);
|
|
95
|
+
if (seconds <= 0) {
|
|
96
|
+
throw new Error('Duration must be positive');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const client = await createClient();
|
|
100
|
+
const runtime = client.runtime as IMockRuntime;
|
|
101
|
+
|
|
102
|
+
const beforeTime = runtime.time.now();
|
|
103
|
+
await runtime.time.advanceTime(seconds);
|
|
104
|
+
const afterTime = runtime.time.now();
|
|
105
|
+
|
|
106
|
+
output.result({
|
|
107
|
+
advanced: seconds,
|
|
108
|
+
advancedReadable: formatDuration(seconds),
|
|
109
|
+
beforeTimestamp: beforeTime,
|
|
110
|
+
afterTimestamp: afterTime,
|
|
111
|
+
afterIso: new Date(afterTime * 1000).toISOString(),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
output.success(`Advanced time by ${formatDuration(seconds)}`);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const structuredError = mapError(error);
|
|
117
|
+
output.errorResult({
|
|
118
|
+
code: structuredError.code,
|
|
119
|
+
message: structuredError.message,
|
|
120
|
+
});
|
|
121
|
+
process.exit(ExitCode.ERROR);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// time set
|
|
128
|
+
// ============================================================================
|
|
129
|
+
|
|
130
|
+
function createTimeSetCommand(): Command {
|
|
131
|
+
return new Command('set')
|
|
132
|
+
.description('Set mock blockchain time to specific timestamp')
|
|
133
|
+
.argument('<timestamp>', 'Unix timestamp or ISO date')
|
|
134
|
+
.option('--json', 'Output as JSON')
|
|
135
|
+
.option('-q, --quiet', 'Minimal output')
|
|
136
|
+
.action(async (timestamp, options) => {
|
|
137
|
+
const output = new Output(
|
|
138
|
+
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
validateMockMode();
|
|
143
|
+
|
|
144
|
+
const targetTime = parseTimestamp(timestamp);
|
|
145
|
+
|
|
146
|
+
const client = await createClient();
|
|
147
|
+
const runtime = client.runtime as IMockRuntime;
|
|
148
|
+
|
|
149
|
+
const beforeTime = runtime.time.now();
|
|
150
|
+
|
|
151
|
+
if (targetTime < beforeTime) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
'Cannot set time in the past.\n' +
|
|
154
|
+
`Current time: ${beforeTime}\n` +
|
|
155
|
+
`Target time: ${targetTime}`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await runtime.time.setTime(targetTime);
|
|
160
|
+
|
|
161
|
+
output.result({
|
|
162
|
+
beforeTimestamp: beforeTime,
|
|
163
|
+
afterTimestamp: targetTime,
|
|
164
|
+
afterIso: new Date(targetTime * 1000).toISOString(),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
output.success(`Set time to ${new Date(targetTime * 1000).toISOString()}`);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
const structuredError = mapError(error);
|
|
170
|
+
output.errorResult({
|
|
171
|
+
code: structuredError.code,
|
|
172
|
+
message: structuredError.message,
|
|
173
|
+
});
|
|
174
|
+
process.exit(ExitCode.ERROR);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ============================================================================
|
|
180
|
+
// Helpers
|
|
181
|
+
// ============================================================================
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Validate that we're in mock mode
|
|
185
|
+
*/
|
|
186
|
+
function validateMockMode(): void {
|
|
187
|
+
const config = loadConfig();
|
|
188
|
+
if (config.mode !== 'mock') {
|
|
189
|
+
throw new Error(
|
|
190
|
+
'Time commands only available in mock mode.\n' +
|
|
191
|
+
`Current mode: ${config.mode}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Parse duration string to seconds
|
|
198
|
+
*
|
|
199
|
+
* Supports:
|
|
200
|
+
* - "30s" - 30 seconds
|
|
201
|
+
* - "5m" - 5 minutes
|
|
202
|
+
* - "2h" - 2 hours
|
|
203
|
+
* - "7d" - 7 days
|
|
204
|
+
* - "3600" - raw seconds
|
|
205
|
+
*/
|
|
206
|
+
function parseDuration(duration: string): number {
|
|
207
|
+
// Raw number (seconds)
|
|
208
|
+
if (/^\d+$/.test(duration)) {
|
|
209
|
+
return parseInt(duration, 10);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Duration with unit
|
|
213
|
+
const match = duration.match(/^(\d+(?:\.\d+)?)(s|m|h|d)$/);
|
|
214
|
+
if (!match) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`Invalid duration format: "${duration}"\n` +
|
|
217
|
+
'Expected format: "30s", "5m", "2h", "7d", or raw seconds'
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const [, valueStr, unit] = match;
|
|
222
|
+
const value = parseFloat(valueStr);
|
|
223
|
+
|
|
224
|
+
switch (unit) {
|
|
225
|
+
case 's':
|
|
226
|
+
return Math.floor(value);
|
|
227
|
+
case 'm':
|
|
228
|
+
return Math.floor(value * 60);
|
|
229
|
+
case 'h':
|
|
230
|
+
return Math.floor(value * 3600);
|
|
231
|
+
case 'd':
|
|
232
|
+
return Math.floor(value * 86400);
|
|
233
|
+
default:
|
|
234
|
+
throw new Error(`Unknown unit: ${unit}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Parse timestamp string (Unix timestamp or ISO date)
|
|
240
|
+
*/
|
|
241
|
+
function parseTimestamp(timestamp: string): number {
|
|
242
|
+
// Unix timestamp (number)
|
|
243
|
+
if (/^\d+$/.test(timestamp)) {
|
|
244
|
+
return parseInt(timestamp, 10);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ISO date string
|
|
248
|
+
const date = new Date(timestamp);
|
|
249
|
+
if (isNaN(date.getTime())) {
|
|
250
|
+
throw new Error(
|
|
251
|
+
`Invalid timestamp: "${timestamp}"\n` +
|
|
252
|
+
'Expected Unix timestamp or ISO date (e.g., "2025-12-31T23:59:59Z")'
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return Math.floor(date.getTime() / 1000);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Format seconds as human-readable duration
|
|
261
|
+
*/
|
|
262
|
+
function formatDuration(seconds: number): string {
|
|
263
|
+
if (seconds < 60) {
|
|
264
|
+
return `${seconds}s`;
|
|
265
|
+
}
|
|
266
|
+
if (seconds < 3600) {
|
|
267
|
+
const minutes = Math.floor(seconds / 60);
|
|
268
|
+
const secs = seconds % 60;
|
|
269
|
+
return secs > 0 ? `${minutes}m ${secs}s` : `${minutes}m`;
|
|
270
|
+
}
|
|
271
|
+
if (seconds < 86400) {
|
|
272
|
+
const hours = Math.floor(seconds / 3600);
|
|
273
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
274
|
+
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const days = Math.floor(seconds / 86400);
|
|
278
|
+
const hours = Math.floor((seconds % 86400) / 3600);
|
|
279
|
+
return hours > 0 ? `${days}d ${hours}h` : `${days}d`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Format timestamp as relative time
|
|
284
|
+
*/
|
|
285
|
+
function formatRelativeTime(timestamp: number): string {
|
|
286
|
+
const now = Math.floor(Date.now() / 1000);
|
|
287
|
+
const diff = timestamp - now;
|
|
288
|
+
|
|
289
|
+
if (Math.abs(diff) < 60) {
|
|
290
|
+
return diff >= 0 ? 'just now' : 'just now';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const absDiff = Math.abs(diff);
|
|
294
|
+
const formatted = formatDuration(absDiff);
|
|
295
|
+
|
|
296
|
+
if (diff > 0) {
|
|
297
|
+
return `${formatted} in the future`;
|
|
298
|
+
} else {
|
|
299
|
+
return `${formatted} in the past`;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export { parseDuration, formatDuration };
|