@agirails/sdk 2.0.0 → 2.0.1-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -116
- package/dist/ACTPClient.d.ts +33 -456
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +93 -477
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/EscrowVault.json +38 -106
- package/dist/builders/DeliveryProofBuilder.d.ts +1 -60
- package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
- package/dist/builders/DeliveryProofBuilder.js +5 -81
- package/dist/builders/DeliveryProofBuilder.js.map +1 -1
- package/dist/builders/QuoteBuilder.d.ts +0 -101
- package/dist/builders/QuoteBuilder.d.ts.map +1 -1
- package/dist/builders/QuoteBuilder.js +3 -120
- package/dist/builders/QuoteBuilder.js.map +1 -1
- package/dist/builders/index.d.ts +0 -4
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +0 -4
- package/dist/builders/index.js.map +1 -1
- package/dist/config/networks.d.ts +0 -28
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +12 -60
- package/dist/config/networks.js.map +1 -1
- package/dist/errors/index.d.ts +2 -165
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -260
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +13 -61
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -141
- package/dist/index.js.map +1 -1
- package/dist/protocol/ACTPKernel.d.ts +2 -229
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +33 -367
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/EASHelper.d.ts +2 -57
- package/dist/protocol/EASHelper.d.ts.map +1 -1
- package/dist/protocol/EASHelper.js +37 -230
- package/dist/protocol/EASHelper.js.map +1 -1
- package/dist/protocol/EscrowVault.d.ts +2 -93
- package/dist/protocol/EscrowVault.d.ts.map +1 -1
- package/dist/protocol/EscrowVault.js +33 -122
- package/dist/protocol/EscrowVault.js.map +1 -1
- package/dist/protocol/EventMonitor.d.ts +1 -45
- package/dist/protocol/EventMonitor.d.ts.map +1 -1
- package/dist/protocol/EventMonitor.js +8 -64
- package/dist/protocol/EventMonitor.js.map +1 -1
- package/dist/protocol/MessageSigner.d.ts +2 -116
- package/dist/protocol/MessageSigner.d.ts.map +1 -1
- package/dist/protocol/MessageSigner.js +9 -215
- package/dist/protocol/MessageSigner.js.map +1 -1
- package/dist/protocol/ProofGenerator.d.ts +0 -93
- package/dist/protocol/ProofGenerator.d.ts.map +1 -1
- package/dist/protocol/ProofGenerator.js +9 -194
- package/dist/protocol/ProofGenerator.js.map +1 -1
- package/dist/protocol/QuoteBuilder.d.ts +0 -8
- package/dist/protocol/QuoteBuilder.d.ts.map +1 -1
- package/dist/protocol/QuoteBuilder.js +0 -8
- package/dist/protocol/QuoteBuilder.js.map +1 -1
- package/dist/types/eip712.d.ts +0 -34
- package/dist/types/eip712.d.ts.map +1 -1
- package/dist/types/eip712.js +5 -31
- package/dist/types/eip712.js.map +1 -1
- package/dist/types/escrow.d.ts +10 -17
- package/dist/types/escrow.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -8
- package/dist/types/index.js.map +1 -1
- package/dist/types/message.d.ts +0 -32
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +0 -4
- package/dist/types/message.js.map +1 -1
- package/dist/types/state.d.ts +0 -28
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/state.js +6 -37
- package/dist/types/state.js.map +1 -1
- package/dist/types/transaction.d.ts +0 -17
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/utils/IPFSClient.d.ts +0 -113
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +7 -128
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/NonceManager.d.ts +1 -234
- package/dist/utils/NonceManager.d.ts.map +1 -1
- package/dist/utils/NonceManager.js +7 -372
- package/dist/utils/NonceManager.js.map +1 -1
- package/dist/utils/ReceivedNonceTracker.d.ts +0 -175
- package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -1
- package/dist/utils/ReceivedNonceTracker.js +5 -261
- package/dist/utils/ReceivedNonceTracker.js.map +1 -1
- package/dist/utils/canonicalJson.d.ts +0 -22
- package/dist/utils/canonicalJson.d.ts.map +1 -1
- package/dist/utils/canonicalJson.js +3 -26
- package/dist/utils/canonicalJson.js.map +1 -1
- package/dist/utils/computeTypeHash.d.ts +0 -14
- package/dist/utils/computeTypeHash.d.ts.map +1 -1
- package/dist/utils/computeTypeHash.js +2 -19
- package/dist/utils/computeTypeHash.js.map +1 -1
- package/dist/utils/validation.d.ts +0 -40
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +7 -184
- package/dist/utils/validation.js.map +1 -1
- package/package.json +37 -54
- package/src/ACTPClient.ts +178 -692
- package/src/__tests__/ProofGenerator.test.ts +124 -0
- package/src/__tests__/QuoteBuilder.test.ts +516 -0
- package/src/__tests__/StateMachine.test.ts +82 -0
- package/src/__tests__/builders/DeliveryProofBuilder.test.ts +581 -0
- package/src/__tests__/integration/ACTPClient.test.ts +263 -0
- package/src/__tests__/integration.test.ts +289 -0
- package/src/__tests__/protocol/EASHelper.test.ts +472 -0
- package/src/__tests__/protocol/EventMonitor.test.ts +382 -0
- package/src/__tests__/security/ACTPKernel.security.test.ts +1167 -0
- package/src/__tests__/security/EscrowVault.security.test.ts +570 -0
- package/src/__tests__/security/MessageSigner.security.test.ts +286 -0
- package/src/__tests__/security/NonceReplay.security.test.ts +501 -0
- package/src/__tests__/security/validation.security.test.ts +376 -0
- package/src/__tests__/utils/IPFSClient.test.ts +262 -0
- package/src/__tests__/utils/NonceManager.test.ts +205 -0
- package/src/__tests__/utils/canonicalJson.test.ts +153 -0
- package/src/abi/EscrowVault.json +38 -106
- package/src/builders/DeliveryProofBuilder.ts +2 -3
- package/src/config/networks.ts +9 -32
- package/src/errors/index.ts +1 -298
- package/src/index.ts +71 -207
- package/src/protocol/ACTPKernel.ts +23 -175
- package/src/protocol/EASHelper.ts +46 -230
- package/src/protocol/EscrowVault.ts +50 -68
- package/src/protocol/EventMonitor.ts +15 -44
- package/src/protocol/MessageSigner.ts +13 -193
- package/src/protocol/ProofGenerator.ts +4 -223
- package/src/types/escrow.ts +11 -12
- package/src/types/index.ts +1 -5
- package/src/types/state.ts +3 -12
- package/src/types/transaction.ts +1 -4
- package/src/utils/IPFSClient.ts +5 -122
- package/src/utils/NonceManager.ts +8 -305
- package/src/utils/ReceivedNonceTracker.ts +0 -170
- package/src/utils/validation.ts +0 -164
- package/LICENSE +0 -190
- package/bin/actp +0 -10
- package/dist/abi/AgentRegistry.json +0 -782
- package/dist/abi/IdentityRegistry.json +0 -316
- package/dist/adapters/BaseAdapter.d.ts +0 -231
- package/dist/adapters/BaseAdapter.d.ts.map +0 -1
- package/dist/adapters/BaseAdapter.js +0 -393
- package/dist/adapters/BaseAdapter.js.map +0 -1
- package/dist/adapters/BeginnerAdapter.d.ts +0 -152
- package/dist/adapters/BeginnerAdapter.d.ts.map +0 -1
- package/dist/adapters/BeginnerAdapter.js +0 -168
- package/dist/adapters/BeginnerAdapter.js.map +0 -1
- package/dist/adapters/IntermediateAdapter.d.ts +0 -211
- package/dist/adapters/IntermediateAdapter.d.ts.map +0 -1
- package/dist/adapters/IntermediateAdapter.js +0 -260
- package/dist/adapters/IntermediateAdapter.js.map +0 -1
- package/dist/adapters/index.d.ts +0 -15
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -26
- package/dist/adapters/index.js.map +0 -1
- package/dist/cli/commands/balance.d.ts +0 -13
- package/dist/cli/commands/balance.d.ts.map +0 -1
- package/dist/cli/commands/balance.js +0 -89
- package/dist/cli/commands/balance.js.map +0 -1
- package/dist/cli/commands/batch.d.ts +0 -24
- package/dist/cli/commands/batch.d.ts.map +0 -1
- package/dist/cli/commands/batch.js +0 -424
- package/dist/cli/commands/batch.js.map +0 -1
- package/dist/cli/commands/config.d.ts +0 -13
- package/dist/cli/commands/config.d.ts.map +0 -1
- package/dist/cli/commands/config.js +0 -192
- package/dist/cli/commands/config.js.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -19
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/init.js +0 -143
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/mint.d.ts +0 -13
- package/dist/cli/commands/mint.d.ts.map +0 -1
- package/dist/cli/commands/mint.js +0 -91
- package/dist/cli/commands/mint.js.map +0 -1
- package/dist/cli/commands/pay.d.ts +0 -18
- package/dist/cli/commands/pay.d.ts.map +0 -1
- package/dist/cli/commands/pay.js +0 -87
- package/dist/cli/commands/pay.js.map +0 -1
- package/dist/cli/commands/simulate.d.ts +0 -32
- package/dist/cli/commands/simulate.d.ts.map +0 -1
- package/dist/cli/commands/simulate.js +0 -290
- package/dist/cli/commands/simulate.js.map +0 -1
- package/dist/cli/commands/time.d.ts +0 -29
- package/dist/cli/commands/time.d.ts.map +0 -1
- package/dist/cli/commands/time.js +0 -252
- package/dist/cli/commands/time.js.map +0 -1
- package/dist/cli/commands/tx.d.ts +0 -16
- package/dist/cli/commands/tx.d.ts.map +0 -1
- package/dist/cli/commands/tx.js +0 -379
- package/dist/cli/commands/tx.js.map +0 -1
- package/dist/cli/commands/watch.d.ts +0 -20
- package/dist/cli/commands/watch.d.ts.map +0 -1
- package/dist/cli/commands/watch.js +0 -160
- package/dist/cli/commands/watch.js.map +0 -1
- package/dist/cli/index.d.ts +0 -17
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -104
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/utils/client.d.ts +0 -70
- package/dist/cli/utils/client.d.ts.map +0 -1
- package/dist/cli/utils/client.js +0 -240
- package/dist/cli/utils/client.js.map +0 -1
- package/dist/cli/utils/config.d.ts +0 -91
- package/dist/cli/utils/config.d.ts.map +0 -1
- package/dist/cli/utils/config.js +0 -240
- package/dist/cli/utils/config.js.map +0 -1
- package/dist/cli/utils/output.d.ts +0 -174
- package/dist/cli/utils/output.d.ts.map +0 -1
- package/dist/cli/utils/output.js +0 -380
- package/dist/cli/utils/output.js.map +0 -1
- package/dist/level0/Provider.d.ts +0 -106
- package/dist/level0/Provider.d.ts.map +0 -1
- package/dist/level0/Provider.js +0 -10
- package/dist/level0/Provider.js.map +0 -1
- package/dist/level0/ServiceDirectory.d.ts +0 -74
- package/dist/level0/ServiceDirectory.d.ts.map +0 -1
- package/dist/level0/ServiceDirectory.js +0 -122
- package/dist/level0/ServiceDirectory.js.map +0 -1
- package/dist/level0/index.d.ts +0 -10
- package/dist/level0/index.d.ts.map +0 -1
- package/dist/level0/index.js +0 -15
- package/dist/level0/index.js.map +0 -1
- package/dist/level0/provide.d.ts +0 -51
- package/dist/level0/provide.d.ts.map +0 -1
- package/dist/level0/provide.js +0 -113
- package/dist/level0/provide.js.map +0 -1
- package/dist/level0/request.d.ts +0 -53
- package/dist/level0/request.d.ts.map +0 -1
- package/dist/level0/request.js +0 -462
- package/dist/level0/request.js.map +0 -1
- package/dist/level1/Agent.d.ts +0 -472
- package/dist/level1/Agent.d.ts.map +0 -1
- package/dist/level1/Agent.js +0 -1091
- package/dist/level1/Agent.js.map +0 -1
- package/dist/level1/index.d.ts +0 -10
- package/dist/level1/index.d.ts.map +0 -1
- package/dist/level1/index.js +0 -30
- package/dist/level1/index.js.map +0 -1
- package/dist/level1/pricing/PriceCalculator.d.ts +0 -62
- package/dist/level1/pricing/PriceCalculator.d.ts.map +0 -1
- package/dist/level1/pricing/PriceCalculator.js +0 -237
- package/dist/level1/pricing/PriceCalculator.js.map +0 -1
- package/dist/level1/pricing/PricingStrategy.d.ts +0 -179
- package/dist/level1/pricing/PricingStrategy.d.ts.map +0 -1
- package/dist/level1/pricing/PricingStrategy.js +0 -11
- package/dist/level1/pricing/PricingStrategy.js.map +0 -1
- package/dist/level1/types/Job.d.ts +0 -166
- package/dist/level1/types/Job.d.ts.map +0 -1
- package/dist/level1/types/Job.js +0 -11
- package/dist/level1/types/Job.js.map +0 -1
- package/dist/level1/types/Options.d.ts +0 -258
- package/dist/level1/types/Options.d.ts.map +0 -1
- package/dist/level1/types/Options.js +0 -8
- package/dist/level1/types/Options.js.map +0 -1
- package/dist/level1/types/index.d.ts +0 -8
- package/dist/level1/types/index.d.ts.map +0 -1
- package/dist/level1/types/index.js +0 -8
- package/dist/level1/types/index.js.map +0 -1
- package/dist/protocol/AgentRegistry.d.ts +0 -177
- package/dist/protocol/AgentRegistry.d.ts.map +0 -1
- package/dist/protocol/AgentRegistry.js +0 -449
- package/dist/protocol/AgentRegistry.js.map +0 -1
- package/dist/protocol/DIDManager.d.ts +0 -289
- package/dist/protocol/DIDManager.d.ts.map +0 -1
- package/dist/protocol/DIDManager.js +0 -481
- package/dist/protocol/DIDManager.js.map +0 -1
- package/dist/protocol/DIDResolver.d.ts +0 -236
- package/dist/protocol/DIDResolver.d.ts.map +0 -1
- package/dist/protocol/DIDResolver.js +0 -495
- package/dist/protocol/DIDResolver.js.map +0 -1
- package/dist/runtime/BlockchainRuntime.d.ts +0 -360
- package/dist/runtime/BlockchainRuntime.d.ts.map +0 -1
- package/dist/runtime/BlockchainRuntime.js +0 -767
- package/dist/runtime/BlockchainRuntime.js.map +0 -1
- package/dist/runtime/IACTPRuntime.d.ts +0 -271
- package/dist/runtime/IACTPRuntime.d.ts.map +0 -1
- package/dist/runtime/IACTPRuntime.js +0 -15
- package/dist/runtime/IACTPRuntime.js.map +0 -1
- package/dist/runtime/MockRuntime.d.ts +0 -445
- package/dist/runtime/MockRuntime.d.ts.map +0 -1
- package/dist/runtime/MockRuntime.js +0 -1065
- package/dist/runtime/MockRuntime.js.map +0 -1
- package/dist/runtime/MockStateManager.d.ts +0 -233
- package/dist/runtime/MockStateManager.d.ts.map +0 -1
- package/dist/runtime/MockStateManager.js +0 -533
- package/dist/runtime/MockStateManager.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -14
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -42
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/types/MockState.d.ts +0 -167
- package/dist/runtime/types/MockState.d.ts.map +0 -1
- package/dist/runtime/types/MockState.js +0 -43
- package/dist/runtime/types/MockState.js.map +0 -1
- package/dist/types/agent.d.ts +0 -76
- package/dist/types/agent.d.ts.map +0 -1
- package/dist/types/agent.js +0 -8
- package/dist/types/agent.js.map +0 -1
- package/dist/types/did.d.ts +0 -192
- package/dist/types/did.d.ts.map +0 -1
- package/dist/types/did.js +0 -38
- package/dist/types/did.js.map +0 -1
- package/dist/utils/ErrorRecoveryGuide.d.ts +0 -125
- package/dist/utils/ErrorRecoveryGuide.d.ts.map +0 -1
- package/dist/utils/ErrorRecoveryGuide.js +0 -579
- package/dist/utils/ErrorRecoveryGuide.js.map +0 -1
- package/dist/utils/Helpers.d.ts +0 -453
- package/dist/utils/Helpers.d.ts.map +0 -1
- package/dist/utils/Helpers.js +0 -623
- package/dist/utils/Helpers.js.map +0 -1
- package/dist/utils/Logger.d.ts +0 -195
- package/dist/utils/Logger.d.ts.map +0 -1
- package/dist/utils/Logger.js +0 -382
- package/dist/utils/Logger.js.map +0 -1
- package/dist/utils/RateLimiter.d.ts +0 -253
- package/dist/utils/RateLimiter.d.ts.map +0 -1
- package/dist/utils/RateLimiter.js +0 -424
- package/dist/utils/RateLimiter.js.map +0 -1
- package/dist/utils/SDKLifecycle.d.ts +0 -156
- package/dist/utils/SDKLifecycle.d.ts.map +0 -1
- package/dist/utils/SDKLifecycle.js +0 -347
- package/dist/utils/SDKLifecycle.js.map +0 -1
- package/dist/utils/SecureNonce.d.ts +0 -57
- package/dist/utils/SecureNonce.d.ts.map +0 -1
- package/dist/utils/SecureNonce.js +0 -80
- package/dist/utils/SecureNonce.js.map +0 -1
- package/dist/utils/Semaphore.d.ts +0 -123
- package/dist/utils/Semaphore.d.ts.map +0 -1
- package/dist/utils/Semaphore.js +0 -247
- package/dist/utils/Semaphore.js.map +0 -1
- package/dist/utils/UsedAttestationTracker.d.ts +0 -167
- package/dist/utils/UsedAttestationTracker.d.ts.map +0 -1
- package/dist/utils/UsedAttestationTracker.js +0 -309
- package/dist/utils/UsedAttestationTracker.js.map +0 -1
- package/dist/utils/fsSafe.d.ts +0 -14
- package/dist/utils/fsSafe.d.ts.map +0 -1
- package/dist/utils/fsSafe.js +0 -89
- package/dist/utils/fsSafe.js.map +0 -1
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -51
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/security.d.ts +0 -147
- package/dist/utils/security.d.ts.map +0 -1
- package/dist/utils/security.js +0 -391
- package/dist/utils/security.js.map +0 -1
- package/src/abi/AgentRegistry.json +0 -782
- package/src/abi/IdentityRegistry.json +0 -316
- package/src/adapters/BaseAdapter.ts +0 -473
- package/src/adapters/BeginnerAdapter.ts +0 -232
- package/src/adapters/IntermediateAdapter.ts +0 -316
- package/src/adapters/index.ts +0 -25
- package/src/cli/commands/balance.ts +0 -110
- package/src/cli/commands/batch.ts +0 -487
- package/src/cli/commands/config.ts +0 -231
- package/src/cli/commands/init.ts +0 -161
- package/src/cli/commands/mint.ts +0 -116
- package/src/cli/commands/pay.ts +0 -113
- package/src/cli/commands/simulate.ts +0 -345
- package/src/cli/commands/time.ts +0 -303
- package/src/cli/commands/tx.ts +0 -448
- package/src/cli/commands/watch.ts +0 -211
- package/src/cli/index.ts +0 -116
- package/src/cli/utils/client.ts +0 -249
- package/src/cli/utils/config.ts +0 -282
- package/src/cli/utils/output.ts +0 -465
- package/src/level0/Provider.ts +0 -117
- package/src/level0/ServiceDirectory.ts +0 -131
- package/src/level0/index.ts +0 -10
- package/src/level0/provide.ts +0 -131
- package/src/level0/request.ts +0 -494
- package/src/level1/Agent.ts +0 -1432
- package/src/level1/index.ts +0 -10
- package/src/level1/pricing/PriceCalculator.ts +0 -255
- package/src/level1/pricing/PricingStrategy.ts +0 -198
- package/src/level1/types/Job.ts +0 -179
- package/src/level1/types/Options.ts +0 -291
- package/src/level1/types/index.ts +0 -8
- package/src/protocol/AgentRegistry.ts +0 -559
- package/src/protocol/DIDManager.ts +0 -629
- package/src/protocol/DIDResolver.ts +0 -554
- package/src/runtime/BlockchainRuntime.ts +0 -993
- package/src/runtime/IACTPRuntime.ts +0 -284
- package/src/runtime/MockRuntime.ts +0 -1244
- package/src/runtime/MockStateManager.ts +0 -576
- package/src/runtime/index.ts +0 -25
- package/src/runtime/types/MockState.ts +0 -227
- package/src/types/agent.ts +0 -79
- package/src/types/did.ts +0 -223
- package/src/utils/ErrorRecoveryGuide.ts +0 -675
- package/src/utils/Helpers.ts +0 -688
- package/src/utils/Logger.ts +0 -484
- package/src/utils/RateLimiter.ts +0 -534
- package/src/utils/SDKLifecycle.ts +0 -416
- package/src/utils/SecureNonce.ts +0 -78
- package/src/utils/Semaphore.ts +0 -276
- package/src/utils/UsedAttestationTracker.ts +0 -387
- package/src/utils/fsSafe.ts +0 -75
- package/src/utils/index.ts +0 -80
- package/src/utils/security.ts +0 -418
package/src/ACTPClient.ts
CHANGED
|
@@ -1,790 +1,276 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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';
|
|
1
|
+
import { ethers, Wallet, Signer } from 'ethers';
|
|
2
|
+
import type { JsonRpcProvider } from 'ethers';
|
|
3
|
+
import { ACTPKernel } from './protocol/ACTPKernel';
|
|
4
|
+
import { EscrowVault } from './protocol/EscrowVault';
|
|
5
|
+
import { EventMonitor } from './protocol/EventMonitor';
|
|
6
|
+
import { ProofGenerator } from './protocol/ProofGenerator';
|
|
7
|
+
import { MessageSigner } from './protocol/MessageSigner';
|
|
8
|
+
import { QuoteBuilder } from './builders/QuoteBuilder';
|
|
9
|
+
import { NetworkConfig, getNetwork } from './config/networks';
|
|
10
|
+
import { NetworkError, ValidationError } from './errors';
|
|
48
11
|
import { EASHelper, EASConfig } from './protocol/EASHelper';
|
|
49
|
-
import {
|
|
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
|
-
// ============================================================================
|
|
12
|
+
import { NonceManager, InMemoryNonceManager } from './utils/NonceManager';
|
|
13
|
+
import { IPFSClient } from './utils/IPFSClient';
|
|
127
14
|
|
|
128
15
|
/**
|
|
129
|
-
*
|
|
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.
|
|
16
|
+
* ACTPClient configuration
|
|
153
17
|
*/
|
|
154
18
|
export interface ACTPClientConfig {
|
|
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
|
-
*/
|
|
19
|
+
network: 'base-sepolia' | 'base-mainnet';
|
|
237
20
|
privateKey?: string;
|
|
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
|
-
*/
|
|
21
|
+
signer?: Signer;
|
|
22
|
+
provider?: JsonRpcProvider;
|
|
247
23
|
rpcUrl?: string;
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Optional: Contract address overrides.
|
|
251
|
-
*
|
|
252
|
-
* Override default deployed contract addresses.
|
|
253
|
-
* Used in 'testnet' and 'mainnet' modes.
|
|
254
|
-
*/
|
|
255
24
|
contracts?: {
|
|
256
25
|
actpKernel?: string;
|
|
257
26
|
escrowVault?: string;
|
|
258
27
|
usdc?: string;
|
|
259
28
|
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Optional: Gas settings for blockchain transactions.
|
|
263
|
-
*
|
|
264
|
-
* Used in 'testnet' and 'mainnet' modes.
|
|
265
|
-
*/
|
|
266
29
|
gasSettings?: {
|
|
267
30
|
maxFeePerGas?: bigint;
|
|
268
31
|
maxPriorityFeePerGas?: bigint;
|
|
269
32
|
};
|
|
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;
|
|
33
|
+
eas?: EASConfig;
|
|
315
34
|
}
|
|
316
35
|
|
|
317
|
-
// ============================================================================
|
|
318
|
-
// ACTPClient Class
|
|
319
|
-
// ============================================================================
|
|
320
|
-
|
|
321
36
|
/**
|
|
322
|
-
* ACTPClient - Main entry point for
|
|
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
|
|
37
|
+
* ACTPClient - Main entry point for ACTP SDK
|
|
332
38
|
*
|
|
333
|
-
*
|
|
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
|
|
39
|
+
* Example:
|
|
346
40
|
* ```typescript
|
|
347
|
-
* // Create client
|
|
348
41
|
* const client = await ACTPClient.create({
|
|
349
|
-
*
|
|
350
|
-
*
|
|
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',
|
|
42
|
+
* network: 'base-sepolia',
|
|
43
|
+
* privateKey: process.env.PRIVATE_KEY
|
|
362
44
|
* });
|
|
363
|
-
* await client.intermediate.linkEscrow(txId);
|
|
364
45
|
*
|
|
365
|
-
*
|
|
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
|
-
* });
|
|
46
|
+
* const txId = await client.kernel.createTransaction({...});
|
|
373
47
|
* ```
|
|
374
48
|
*/
|
|
375
49
|
export class ACTPClient {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
* console.log('Transaction ID:', result.txId);
|
|
390
|
-
* console.log('State:', result.state); // 'COMMITTED'
|
|
391
|
-
* ```
|
|
392
|
-
*/
|
|
393
|
-
public readonly beginner: BeginnerAdapter;
|
|
50
|
+
public readonly kernel: ACTPKernel;
|
|
51
|
+
public readonly escrow: EscrowVault;
|
|
52
|
+
public readonly events: EventMonitor;
|
|
53
|
+
public readonly proofGenerator: ProofGenerator;
|
|
54
|
+
public readonly messageSigner: MessageSigner;
|
|
55
|
+
public readonly quote: QuoteBuilder;
|
|
56
|
+
public readonly eas?: EASHelper;
|
|
57
|
+
|
|
58
|
+
private readonly provider: JsonRpcProvider;
|
|
59
|
+
private readonly signer: Signer;
|
|
60
|
+
private readonly networkConfig: NetworkConfig;
|
|
61
|
+
private readonly nonceManager: NonceManager;
|
|
62
|
+
private readonly ipfs?: IPFSClient;
|
|
394
63
|
|
|
395
64
|
/**
|
|
396
|
-
*
|
|
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
|
-
* ```
|
|
416
|
-
*/
|
|
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`.
|
|
65
|
+
* Private constructor - use ACTPClient.create() instead
|
|
424
66
|
*/
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
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');
|
|
67
|
+
private constructor(config: ACTPClientConfig) {
|
|
68
|
+
// Validate config
|
|
69
|
+
this.validateConfig(config);
|
|
70
|
+
|
|
71
|
+
// Get network configuration (already cloned in getNetwork)
|
|
72
|
+
this.networkConfig = getNetwork(config.network);
|
|
73
|
+
|
|
74
|
+
// Apply overrides immutably (create new objects, don't mutate)
|
|
75
|
+
if (config.contracts) {
|
|
76
|
+
this.networkConfig = {
|
|
77
|
+
...this.networkConfig,
|
|
78
|
+
contracts: {
|
|
79
|
+
...this.networkConfig.contracts,
|
|
80
|
+
...config.contracts
|
|
81
|
+
}
|
|
82
|
+
};
|
|
496
83
|
}
|
|
497
84
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
85
|
+
// Apply gas settings overrides
|
|
86
|
+
if (config.gasSettings) {
|
|
87
|
+
this.networkConfig = {
|
|
88
|
+
...this.networkConfig,
|
|
89
|
+
gasSettings: {
|
|
90
|
+
...this.networkConfig.gasSettings,
|
|
91
|
+
...config.gasSettings
|
|
92
|
+
}
|
|
93
|
+
};
|
|
503
94
|
}
|
|
504
95
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
96
|
+
// Freeze config to prevent accidental mutation
|
|
97
|
+
Object.freeze(this.networkConfig.contracts);
|
|
98
|
+
Object.freeze(this.networkConfig.gasSettings);
|
|
99
|
+
Object.freeze(this.networkConfig);
|
|
508
100
|
|
|
509
|
-
//
|
|
510
|
-
if (config.
|
|
511
|
-
|
|
101
|
+
// Setup provider
|
|
102
|
+
if (config.provider) {
|
|
103
|
+
this.provider = config.provider;
|
|
512
104
|
} else {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
// SECURITY FIX: Enhanced path validation to prevent path traversal attacks
|
|
517
|
-
if (config.stateDirectory) {
|
|
518
|
-
validateStateDirectory(config.stateDirectory);
|
|
519
|
-
}
|
|
520
|
-
|
|
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
|
-
}
|
|
528
|
-
|
|
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
|
-
}
|
|
105
|
+
const rpcUrl = config.rpcUrl || this.networkConfig.rpcUrl;
|
|
106
|
+
this.provider = new ethers.JsonRpcProvider(rpcUrl, this.networkConfig.chainId);
|
|
107
|
+
}
|
|
537
108
|
|
|
538
|
-
|
|
539
|
-
|
|
109
|
+
// Setup signer
|
|
110
|
+
if (config.signer) {
|
|
111
|
+
this.signer = config.signer;
|
|
112
|
+
} else if (config.privateKey) {
|
|
113
|
+
this.signer = new Wallet(config.privateKey, this.provider);
|
|
114
|
+
} else {
|
|
115
|
+
// Attempt to derive signer from provider if possible
|
|
116
|
+
// In ethers v6, getSigner() is async and returns a JsonRpcSigner
|
|
117
|
+
throw new ValidationError('signer', 'Either privateKey or signer must be provided');
|
|
118
|
+
}
|
|
540
119
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const rpcUrl = config.rpcUrl ?? getNetwork(network).rpcUrl;
|
|
120
|
+
// Initialize shared utilities
|
|
121
|
+
this.nonceManager = new InMemoryNonceManager();
|
|
544
122
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
123
|
+
// Initialize IPFS client if configured
|
|
124
|
+
if (config.rpcUrl) {
|
|
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
|
+
}
|
|
551
128
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
129
|
+
// Initialize protocol modules
|
|
130
|
+
this.kernel = new ACTPKernel(
|
|
131
|
+
this.networkConfig.contracts.actpKernel,
|
|
132
|
+
this.signer,
|
|
133
|
+
this.networkConfig.gasSettings
|
|
134
|
+
);
|
|
555
135
|
|
|
556
|
-
|
|
136
|
+
this.escrow = new EscrowVault(
|
|
137
|
+
this.networkConfig.contracts.escrowVault,
|
|
138
|
+
this.signer,
|
|
139
|
+
this.networkConfig.gasSettings
|
|
140
|
+
);
|
|
557
141
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
provider,
|
|
563
|
-
contracts: config.contracts,
|
|
564
|
-
gasSettings: config.gasSettings,
|
|
565
|
-
easConfig: config.easConfig,
|
|
566
|
-
requireAttestation,
|
|
567
|
-
stateDirectory: config.stateDirectory,
|
|
568
|
-
});
|
|
142
|
+
this.events = new EventMonitor(
|
|
143
|
+
this.kernel['contract'], // Access private contract field
|
|
144
|
+
this.escrow['contract']
|
|
145
|
+
);
|
|
569
146
|
|
|
570
|
-
|
|
571
|
-
await blockchainRuntime.initialize();
|
|
147
|
+
this.proofGenerator = new ProofGenerator();
|
|
572
148
|
|
|
573
|
-
|
|
149
|
+
this.messageSigner = new MessageSigner(this.signer);
|
|
574
150
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
if (config.easConfig) {
|
|
578
|
-
easHelper = blockchainRuntime.getEASHelper();
|
|
579
|
-
}
|
|
580
|
-
break;
|
|
581
|
-
}
|
|
151
|
+
// Initialize QuoteBuilder (AIP-2)
|
|
152
|
+
this.quote = new QuoteBuilder(this.signer, this.nonceManager, this.ipfs);
|
|
582
153
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
`Unknown mode: "${config.mode}". ` +
|
|
586
|
-
'Supported modes: "mock", "testnet", "mainnet"'
|
|
587
|
-
);
|
|
588
|
-
}
|
|
154
|
+
if (config.eas) {
|
|
155
|
+
this.eas = new EASHelper(this.signer, config.eas);
|
|
589
156
|
}
|
|
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);
|
|
602
157
|
}
|
|
603
158
|
|
|
604
|
-
// ==========================================================================
|
|
605
|
-
// Public Methods
|
|
606
|
-
// ==========================================================================
|
|
607
|
-
|
|
608
159
|
/**
|
|
609
|
-
*
|
|
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
|
-
* ```
|
|
160
|
+
* Create and initialize ACTPClient (async factory pattern)
|
|
161
|
+
* Ensures all async components (EIP-712 domain) are ready before returning
|
|
635
162
|
*/
|
|
636
|
-
|
|
637
|
-
|
|
163
|
+
static async create(config: ACTPClientConfig): Promise<ACTPClient> {
|
|
164
|
+
const client = new ACTPClient(config);
|
|
165
|
+
|
|
166
|
+
// Initialize EIP-712 domain for message signing
|
|
167
|
+
await client.messageSigner.initDomain(client.networkConfig.contracts.actpKernel);
|
|
168
|
+
|
|
169
|
+
return client;
|
|
638
170
|
}
|
|
639
171
|
|
|
640
172
|
/**
|
|
641
|
-
*
|
|
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
|
-
* ```
|
|
173
|
+
* @deprecated Use ACTPClient.create() instead
|
|
174
|
+
* Initialize async components (must be called after construction)
|
|
654
175
|
*/
|
|
655
|
-
|
|
656
|
-
|
|
176
|
+
async initialize(): Promise<void> {
|
|
177
|
+
await this.messageSigner.initDomain(this.networkConfig.contracts.actpKernel);
|
|
657
178
|
}
|
|
658
179
|
|
|
659
180
|
/**
|
|
660
|
-
*
|
|
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
|
-
* ```
|
|
181
|
+
* Get signer address
|
|
670
182
|
*/
|
|
671
|
-
|
|
672
|
-
return this.
|
|
183
|
+
async getAddress(): Promise<string> {
|
|
184
|
+
return await this.signer.getAddress();
|
|
673
185
|
}
|
|
674
186
|
|
|
675
187
|
/**
|
|
676
|
-
*
|
|
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
|
-
* ```
|
|
188
|
+
* Get network configuration
|
|
688
189
|
*/
|
|
689
|
-
|
|
690
|
-
|
|
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();
|
|
190
|
+
getNetworkConfig(): NetworkConfig {
|
|
191
|
+
return this.networkConfig;
|
|
701
192
|
}
|
|
702
193
|
|
|
703
194
|
/**
|
|
704
|
-
*
|
|
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
|
|
195
|
+
* Get provider
|
|
710
196
|
*/
|
|
711
|
-
|
|
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
|
-
};
|
|
197
|
+
getProvider(): JsonRpcProvider {
|
|
198
|
+
return this.provider;
|
|
720
199
|
}
|
|
721
200
|
|
|
722
201
|
/**
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
* SECURITY FIX (HIGH-4): Prevents private key exposure in logs.
|
|
202
|
+
* Get current block number
|
|
726
203
|
*/
|
|
727
|
-
|
|
728
|
-
|
|
204
|
+
async getBlockNumber(): Promise<number> {
|
|
205
|
+
try {
|
|
206
|
+
return await this.provider.getBlockNumber();
|
|
207
|
+
} catch (error: any) {
|
|
208
|
+
throw new NetworkError(this.networkConfig.name, error.message);
|
|
209
|
+
}
|
|
729
210
|
}
|
|
730
211
|
|
|
731
212
|
/**
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
* SECURITY FIX (HIGH-4): Prevents private key exposure in console output.
|
|
213
|
+
* Get gas price (ethers v6: use getFeeData instead)
|
|
735
214
|
*/
|
|
736
|
-
|
|
737
|
-
|
|
215
|
+
async getGasPrice() {
|
|
216
|
+
try {
|
|
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
|
+
}
|
|
738
222
|
}
|
|
739
223
|
|
|
740
224
|
/**
|
|
741
|
-
*
|
|
225
|
+
* Release escrow with automatic attestation verification (recommended for security).
|
|
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.
|
|
742
230
|
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
231
|
+
* ACTPKernel V1 contract accepts any attestationUID without on-chain validation.
|
|
232
|
+
* This SDK-side verification is the recommended protection until V2 adds on-chain checks.
|
|
745
233
|
*
|
|
746
|
-
* @param
|
|
747
|
-
* @param
|
|
748
|
-
* @throws {Error} If
|
|
234
|
+
* @param txId - Transaction ID to settle
|
|
235
|
+
* @param attestationUID - EAS attestation UID to verify
|
|
236
|
+
* @throws {Error} If EAS is not configured (client.eas is undefined)
|
|
237
|
+
* @throws {Error} If attestation verification fails (revoked, expired, or txId mismatch)
|
|
238
|
+
* @throws {TransactionRevertedError} If escrow release fails
|
|
749
239
|
*
|
|
750
240
|
* @example
|
|
751
241
|
* ```typescript
|
|
752
|
-
* //
|
|
753
|
-
* await client.
|
|
242
|
+
* // Get transaction to find attestation UID
|
|
243
|
+
* const tx = await client.kernel.getTransaction(txId);
|
|
244
|
+
*
|
|
245
|
+
* // Verify and release escrow in one call
|
|
246
|
+
* await client.releaseEscrowWithVerification(txId, tx.attestationUID);
|
|
754
247
|
* ```
|
|
755
248
|
*/
|
|
756
|
-
async
|
|
757
|
-
|
|
249
|
+
async releaseEscrowWithVerification(txId: string, attestationUID: string): Promise<void> {
|
|
250
|
+
// Ensure EAS is configured
|
|
251
|
+
if (!this.eas) {
|
|
758
252
|
throw new Error(
|
|
759
|
-
|
|
253
|
+
'EAS is not configured. Initialize ACTPClient with eas config or use kernel.releaseEscrow() directly (unsafe)'
|
|
760
254
|
);
|
|
761
255
|
}
|
|
762
256
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}
|
|
257
|
+
// Step 1: Verify attestation belongs to this transaction
|
|
258
|
+
await this.eas.verifyDeliveryAttestation(txId, attestationUID);
|
|
766
259
|
|
|
767
|
-
|
|
260
|
+
// Step 2: Release escrow (verification passed)
|
|
261
|
+
await this.kernel.releaseEscrow(txId);
|
|
768
262
|
}
|
|
769
263
|
|
|
770
264
|
/**
|
|
771
|
-
*
|
|
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
|
-
* ```
|
|
265
|
+
* Validate configuration
|
|
782
266
|
*/
|
|
783
|
-
|
|
784
|
-
if (!
|
|
785
|
-
throw new
|
|
267
|
+
private validateConfig(config: ACTPClientConfig): void {
|
|
268
|
+
if (!config.network) {
|
|
269
|
+
throw new ValidationError('network', 'Network is required');
|
|
786
270
|
}
|
|
787
271
|
|
|
788
|
-
|
|
272
|
+
if (!config.privateKey && !config.signer && !config.provider) {
|
|
273
|
+
throw new ValidationError('auth', 'Provide either privateKey, signer, or provider with signer access');
|
|
274
|
+
}
|
|
789
275
|
}
|
|
790
276
|
}
|