@agirails/sdk 2.5.3 → 2.5.4
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/dist/ACTPClient.d.ts +18 -0
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +67 -22
- package/dist/ACTPClient.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +12 -0
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +30 -4
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/StandardAdapter.d.ts +20 -3
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +45 -11
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/cli/commands/publish.js +16 -4
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/register.js +16 -4
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/tx.js +31 -3
- package/dist/cli/commands/tx.js.map +1 -1
- package/dist/config/networks.d.ts +2 -2
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +27 -22
- package/dist/config/networks.js.map +1 -1
- package/dist/level0/request.d.ts.map +1 -1
- package/dist/level0/request.js +2 -1
- package/dist/level0/request.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +11 -5
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/utils/IPFSClient.d.ts +3 -1
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +27 -7
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
- package/dist/wallet/AutoWalletProvider.js +52 -18
- package/dist/wallet/AutoWalletProvider.js.map +1 -1
- package/dist/wallet/SmartWalletRouter.d.ts +116 -0
- package/dist/wallet/SmartWalletRouter.d.ts.map +1 -0
- package/dist/wallet/SmartWalletRouter.js +212 -0
- package/dist/wallet/SmartWalletRouter.js.map +1 -0
- package/dist/wallet/aa/DualNonceManager.d.ts +19 -0
- package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
- package/dist/wallet/aa/DualNonceManager.js +100 -5
- package/dist/wallet/aa/DualNonceManager.js.map +1 -1
- package/package.json +3 -6
- package/src/ACTPClient.ts +0 -1579
- package/src/abi/ACTPKernel.json +0 -1356
- package/src/abi/AgentRegistry.json +0 -915
- package/src/abi/ERC20.json +0 -40
- package/src/abi/EscrowVault.json +0 -134
- package/src/abi/IdentityRegistry.json +0 -316
- package/src/adapters/AdapterRegistry.ts +0 -173
- package/src/adapters/AdapterRouter.ts +0 -416
- package/src/adapters/BaseAdapter.ts +0 -498
- package/src/adapters/BasicAdapter.ts +0 -514
- package/src/adapters/IAdapter.ts +0 -292
- package/src/adapters/StandardAdapter.ts +0 -555
- package/src/adapters/X402Adapter.ts +0 -731
- package/src/adapters/index.ts +0 -60
- package/src/builders/DeliveryProofBuilder.ts +0 -327
- package/src/builders/QuoteBuilder.ts +0 -483
- package/src/builders/index.ts +0 -17
- 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/deploy-check.ts +0 -364
- package/src/cli/commands/deploy-env.ts +0 -120
- package/src/cli/commands/diff.ts +0 -141
- package/src/cli/commands/init.ts +0 -469
- package/src/cli/commands/mint.ts +0 -116
- package/src/cli/commands/pay.ts +0 -113
- package/src/cli/commands/publish.ts +0 -475
- package/src/cli/commands/pull.ts +0 -124
- package/src/cli/commands/register.ts +0 -247
- package/src/cli/commands/simulate.ts +0 -345
- package/src/cli/commands/time.ts +0 -302
- package/src/cli/commands/tx.ts +0 -448
- package/src/cli/commands/watch.ts +0 -211
- package/src/cli/index.ts +0 -134
- package/src/cli/utils/client.ts +0 -252
- package/src/cli/utils/config.ts +0 -389
- package/src/cli/utils/output.ts +0 -465
- package/src/cli/utils/wallet.ts +0 -109
- package/src/config/agirailsmd.ts +0 -262
- package/src/config/networks.ts +0 -275
- package/src/config/pendingPublish.ts +0 -237
- package/src/config/publishPipeline.ts +0 -359
- package/src/config/syncOperations.ts +0 -279
- package/src/erc8004/ERC8004Bridge.ts +0 -462
- package/src/erc8004/ReputationReporter.ts +0 -468
- package/src/erc8004/index.ts +0 -61
- package/src/errors/index.ts +0 -427
- package/src/index.ts +0 -364
- 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 -132
- package/src/level0/request.ts +0 -432
- package/src/level1/Agent.ts +0 -1426
- 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/ACTPKernel.ts +0 -808
- package/src/protocol/AgentRegistry.ts +0 -559
- package/src/protocol/DIDManager.ts +0 -629
- package/src/protocol/DIDResolver.ts +0 -554
- package/src/protocol/EASHelper.ts +0 -378
- package/src/protocol/EscrowVault.ts +0 -255
- package/src/protocol/EventMonitor.ts +0 -204
- package/src/protocol/MessageSigner.ts +0 -510
- package/src/protocol/ProofGenerator.ts +0 -339
- package/src/protocol/QuoteBuilder.ts +0 -15
- package/src/registry/AgentRegistryClient.ts +0 -202
- package/src/runtime/BlockchainRuntime.ts +0 -1015
- package/src/runtime/IACTPRuntime.ts +0 -306
- package/src/runtime/MockRuntime.ts +0 -1298
- package/src/runtime/MockStateManager.ts +0 -577
- package/src/runtime/index.ts +0 -25
- package/src/runtime/types/MockState.ts +0 -237
- package/src/storage/ArchiveBundleBuilder.ts +0 -561
- package/src/storage/ArweaveClient.ts +0 -946
- package/src/storage/FilebaseClient.ts +0 -790
- package/src/storage/index.ts +0 -96
- package/src/storage/types.ts +0 -348
- package/src/types/adapter.ts +0 -310
- package/src/types/agent.ts +0 -79
- package/src/types/did.ts +0 -223
- package/src/types/eip712.ts +0 -175
- package/src/types/erc8004.ts +0 -293
- package/src/types/escrow.ts +0 -27
- package/src/types/index.ts +0 -17
- package/src/types/message.ts +0 -145
- package/src/types/state.ts +0 -87
- package/src/types/transaction.ts +0 -69
- package/src/types/x402.ts +0 -251
- package/src/utils/ErrorRecoveryGuide.ts +0 -676
- package/src/utils/Helpers.ts +0 -688
- package/src/utils/IPFSClient.ts +0 -368
- package/src/utils/Logger.ts +0 -484
- package/src/utils/NonceManager.ts +0 -591
- package/src/utils/RateLimiter.ts +0 -534
- package/src/utils/ReceivedNonceTracker.ts +0 -567
- 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 -385
- package/src/utils/canonicalJson.ts +0 -38
- package/src/utils/circuitBreaker.ts +0 -324
- package/src/utils/computeTypeHash.ts +0 -48
- package/src/utils/fsSafe.ts +0 -80
- package/src/utils/index.ts +0 -80
- package/src/utils/retry.ts +0 -364
- package/src/utils/security.ts +0 -418
- package/src/utils/validation.ts +0 -540
- package/src/wallet/AutoWalletProvider.ts +0 -299
- package/src/wallet/EOAWalletProvider.ts +0 -69
- package/src/wallet/IWalletProvider.ts +0 -135
- package/src/wallet/aa/BundlerClient.ts +0 -274
- package/src/wallet/aa/DualNonceManager.ts +0 -173
- package/src/wallet/aa/PaymasterClient.ts +0 -174
- package/src/wallet/aa/TransactionBatcher.ts +0 -353
- package/src/wallet/aa/UserOpBuilder.ts +0 -246
- package/src/wallet/aa/constants.ts +0 -60
- package/src/wallet/keystore.ts +0 -240
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SmartWalletRouter - Shared utility for routing state transitions through Smart Wallet.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes the logic for encoding ACTPKernel contract calls as TransactionRequests,
|
|
5
|
+
* validating release preconditions, and verifying attestations. Used by BasicAdapter,
|
|
6
|
+
* StandardAdapter, and ACTPClient to avoid code triplication.
|
|
7
|
+
*
|
|
8
|
+
* @module wallet/SmartWalletRouter
|
|
9
|
+
*/
|
|
10
|
+
import { IWalletProvider, TransactionRequest, TransactionReceipt } from './IWalletProvider';
|
|
11
|
+
import { IACTPRuntime } from '../runtime/IACTPRuntime';
|
|
12
|
+
import { EASHelper } from '../protocol/EASHelper';
|
|
13
|
+
import type { MockTransaction } from '../runtime/types/MockState';
|
|
14
|
+
/**
|
|
15
|
+
* Contract addresses needed for encoding Smart Wallet calls.
|
|
16
|
+
*/
|
|
17
|
+
export interface SmartWalletContractAddresses {
|
|
18
|
+
usdc: string;
|
|
19
|
+
actpKernel: string;
|
|
20
|
+
escrowVault: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* SmartWalletRouter centralizes Smart Wallet routing logic.
|
|
24
|
+
*
|
|
25
|
+
* When a wallet provider with batched support is available (ERC-4337 Smart Wallet),
|
|
26
|
+
* state transitions must be sent as UserOps through the wallet provider so that
|
|
27
|
+
* msg.sender equals the Smart Wallet address (not the EOA signer).
|
|
28
|
+
*/
|
|
29
|
+
export declare class SmartWalletRouter {
|
|
30
|
+
private readonly walletProvider;
|
|
31
|
+
private readonly contractAddresses;
|
|
32
|
+
private readonly runtime;
|
|
33
|
+
private readonly easHelper?;
|
|
34
|
+
constructor(walletProvider: IWalletProvider, contractAddresses: SmartWalletContractAddresses, runtime: IACTPRuntime, easHelper?: EASHelper | undefined);
|
|
35
|
+
/**
|
|
36
|
+
* Check if state transitions should route through the wallet provider.
|
|
37
|
+
* True when walletProvider supports batching (i.e., is a Smart Wallet).
|
|
38
|
+
*/
|
|
39
|
+
shouldRoute(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Encode a transitionState call as a TransactionRequest.
|
|
42
|
+
*/
|
|
43
|
+
encodeTransitionStateTx(txId: string, stateValue: number, proof?: string): TransactionRequest;
|
|
44
|
+
/**
|
|
45
|
+
* Encode a SETTLED state transition as a TransactionRequest.
|
|
46
|
+
* Mirrors BlockchainRuntime.releaseEscrow() secure settlement flow.
|
|
47
|
+
*/
|
|
48
|
+
encodeSettleTx(txId: string): TransactionRequest;
|
|
49
|
+
/**
|
|
50
|
+
* Send a state transition through the wallet provider and check the receipt.
|
|
51
|
+
*
|
|
52
|
+
* @param txId - Transaction ID
|
|
53
|
+
* @param stateValue - Target state value (from TransactionStateValue enum)
|
|
54
|
+
* @param proof - Optional proof data
|
|
55
|
+
* @param label - Human-readable label for error messages (e.g., "startWork", "deliver")
|
|
56
|
+
* @returns Transaction receipt
|
|
57
|
+
*/
|
|
58
|
+
sendTransition(txId: string, stateValue: number, proof?: string, label?: string): Promise<TransactionReceipt>;
|
|
59
|
+
/**
|
|
60
|
+
* Send a SETTLED transition through the wallet provider.
|
|
61
|
+
*
|
|
62
|
+
* @param txId - Transaction ID
|
|
63
|
+
* @returns Transaction receipt
|
|
64
|
+
*/
|
|
65
|
+
sendSettle(txId: string): Promise<TransactionReceipt>;
|
|
66
|
+
/**
|
|
67
|
+
* Validate release preconditions (state + dispute window).
|
|
68
|
+
*
|
|
69
|
+
* Handles both mock mode (disputeWindow = duration in seconds) and
|
|
70
|
+
* blockchain mode (disputeWindow = absolute timestamp). Uses a heuristic:
|
|
71
|
+
* values > 1 billion are absolute timestamps, smaller values are durations.
|
|
72
|
+
*
|
|
73
|
+
* @param txOrId - Transaction object or transaction ID to fetch
|
|
74
|
+
* @returns The validated transaction object (avoids double-fetch)
|
|
75
|
+
*/
|
|
76
|
+
validateReleasePreconditions(txOrId: string | MockTransaction): Promise<MockTransaction>;
|
|
77
|
+
/**
|
|
78
|
+
* Verify/require attestation for wallet-routed release calls.
|
|
79
|
+
*
|
|
80
|
+
* Includes txId cross-check to prevent attestation replay attacks:
|
|
81
|
+
* ensures the provided attestation belongs to the transaction being released.
|
|
82
|
+
*
|
|
83
|
+
* @param txId - Transaction ID being released
|
|
84
|
+
* @param attestationUID - Optional attestation UID
|
|
85
|
+
*/
|
|
86
|
+
verifyReleaseAttestation(txId: string, attestationUID?: string): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Extract txId from escrowId, handling legacy format.
|
|
89
|
+
*
|
|
90
|
+
* @param escrowId - Escrow ID (may be txId or legacy "escrow-{txId}-{timestamp}" format)
|
|
91
|
+
* @returns The txId
|
|
92
|
+
*/
|
|
93
|
+
static extractTxId(escrowId: string): string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Compute the absolute end-time of the dispute window.
|
|
97
|
+
*
|
|
98
|
+
* Handles both representations transparently:
|
|
99
|
+
* - **Mock mode**: `disputeWindow` is a duration in seconds → `completedAt + disputeWindow`
|
|
100
|
+
* - **Blockchain mode**: `disputeWindow` is an absolute timestamp from on-chain → used as-is
|
|
101
|
+
*
|
|
102
|
+
* Heuristic: values > 1 billion are absolute timestamps (post-2001 epoch).
|
|
103
|
+
* Dispute window durations max at 30 days (~2.6M seconds). No overlap.
|
|
104
|
+
*
|
|
105
|
+
* @param completedAt - Delivery timestamp (0 in blockchain V1, real value in mock/V2)
|
|
106
|
+
* @param disputeWindow - Duration in seconds (mock) or absolute timestamp (blockchain)
|
|
107
|
+
* @returns Absolute timestamp when dispute window ends
|
|
108
|
+
*/
|
|
109
|
+
export declare function computeDisputeWindowEnds(completedAt: number, disputeWindow: number): number;
|
|
110
|
+
/**
|
|
111
|
+
* Factory function to create a SmartWalletRouter if wallet provider supports batching.
|
|
112
|
+
*
|
|
113
|
+
* @returns SmartWalletRouter instance if Smart Wallet is available, undefined otherwise
|
|
114
|
+
*/
|
|
115
|
+
export declare function createSmartWalletRouter(walletProvider?: IWalletProvider, contractAddresses?: SmartWalletContractAddresses, runtime?: IACTPRuntime, easHelper?: EASHelper): SmartWalletRouter | undefined;
|
|
116
|
+
//# sourceMappingURL=SmartWalletRouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmartWalletRouter.d.ts","sourceRoot":"","sources":["../../src/wallet/SmartWalletRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAkBlE;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAHV,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,4BAA4B,EAC/C,OAAO,EAAE,YAAY,EACrB,SAAS,CAAC,uBAAW;IAGxC;;;OAGG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,kBAAkB;IAOnG;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB;IAIhD;;;;;;;;OAQG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,EAAE,KAAK,GAAE,MAA0B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAS5I;;;;;OAKG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAS3D;;;;;;;;;OASG;IACG,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IA2C9F;;;;;;;;OAQG;IACG,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BpF;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAI7C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAO3F;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,CAAC,EAAE,eAAe,EAChC,iBAAiB,CAAC,EAAE,4BAA4B,EAChD,OAAO,CAAC,EAAE,YAAY,EACtB,SAAS,CAAC,EAAE,SAAS,GACpB,iBAAiB,GAAG,SAAS,CAK/B"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SmartWalletRouter - Shared utility for routing state transitions through Smart Wallet.
|
|
4
|
+
*
|
|
5
|
+
* Centralizes the logic for encoding ACTPKernel contract calls as TransactionRequests,
|
|
6
|
+
* validating release preconditions, and verifying attestations. Used by BasicAdapter,
|
|
7
|
+
* StandardAdapter, and ACTPClient to avoid code triplication.
|
|
8
|
+
*
|
|
9
|
+
* @module wallet/SmartWalletRouter
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createSmartWalletRouter = exports.computeDisputeWindowEnds = exports.SmartWalletRouter = void 0;
|
|
13
|
+
const ethers_1 = require("ethers");
|
|
14
|
+
const MockState_1 = require("../runtime/types/MockState");
|
|
15
|
+
/**
|
|
16
|
+
* Pre-compiled ABI interface for ACTPKernel.transitionState().
|
|
17
|
+
* Module-level constant to avoid re-instantiation on every call.
|
|
18
|
+
*/
|
|
19
|
+
const ACTP_KERNEL_IFACE = new ethers_1.ethers.Interface([
|
|
20
|
+
'function transitionState(bytes32 transactionId, uint8 newState, bytes proof)',
|
|
21
|
+
]);
|
|
22
|
+
/**
|
|
23
|
+
* Threshold to distinguish absolute timestamps from durations.
|
|
24
|
+
* Dispute window durations max at 30 days (~2.6M seconds).
|
|
25
|
+
* Absolute timestamps (post-2001) are > 1 billion.
|
|
26
|
+
* There's no overlap between these ranges.
|
|
27
|
+
*/
|
|
28
|
+
const ABSOLUTE_TIMESTAMP_THRESHOLD = 1000000000;
|
|
29
|
+
/**
|
|
30
|
+
* SmartWalletRouter centralizes Smart Wallet routing logic.
|
|
31
|
+
*
|
|
32
|
+
* When a wallet provider with batched support is available (ERC-4337 Smart Wallet),
|
|
33
|
+
* state transitions must be sent as UserOps through the wallet provider so that
|
|
34
|
+
* msg.sender equals the Smart Wallet address (not the EOA signer).
|
|
35
|
+
*/
|
|
36
|
+
class SmartWalletRouter {
|
|
37
|
+
constructor(walletProvider, contractAddresses, runtime, easHelper) {
|
|
38
|
+
this.walletProvider = walletProvider;
|
|
39
|
+
this.contractAddresses = contractAddresses;
|
|
40
|
+
this.runtime = runtime;
|
|
41
|
+
this.easHelper = easHelper;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if state transitions should route through the wallet provider.
|
|
45
|
+
* True when walletProvider supports batching (i.e., is a Smart Wallet).
|
|
46
|
+
*/
|
|
47
|
+
shouldRoute() {
|
|
48
|
+
return !!this.walletProvider.payACTPBatched;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Encode a transitionState call as a TransactionRequest.
|
|
52
|
+
*/
|
|
53
|
+
encodeTransitionStateTx(txId, stateValue, proof = '0x') {
|
|
54
|
+
return {
|
|
55
|
+
to: this.contractAddresses.actpKernel,
|
|
56
|
+
data: ACTP_KERNEL_IFACE.encodeFunctionData('transitionState', [txId, stateValue, proof]),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Encode a SETTLED state transition as a TransactionRequest.
|
|
61
|
+
* Mirrors BlockchainRuntime.releaseEscrow() secure settlement flow.
|
|
62
|
+
*/
|
|
63
|
+
encodeSettleTx(txId) {
|
|
64
|
+
return this.encodeTransitionStateTx(txId, MockState_1.TransactionStateValue.SETTLED, '0x');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Send a state transition through the wallet provider and check the receipt.
|
|
68
|
+
*
|
|
69
|
+
* @param txId - Transaction ID
|
|
70
|
+
* @param stateValue - Target state value (from TransactionStateValue enum)
|
|
71
|
+
* @param proof - Optional proof data
|
|
72
|
+
* @param label - Human-readable label for error messages (e.g., "startWork", "deliver")
|
|
73
|
+
* @returns Transaction receipt
|
|
74
|
+
*/
|
|
75
|
+
async sendTransition(txId, stateValue, proof = '0x', label = 'transitionState') {
|
|
76
|
+
const tx = this.encodeTransitionStateTx(txId, stateValue, proof);
|
|
77
|
+
const receipt = await this.walletProvider.sendTransaction(tx);
|
|
78
|
+
if (!receipt.success) {
|
|
79
|
+
throw new Error(`${label} UserOp failed: ${receipt.hash}`);
|
|
80
|
+
}
|
|
81
|
+
return receipt;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Send a SETTLED transition through the wallet provider.
|
|
85
|
+
*
|
|
86
|
+
* @param txId - Transaction ID
|
|
87
|
+
* @returns Transaction receipt
|
|
88
|
+
*/
|
|
89
|
+
async sendSettle(txId) {
|
|
90
|
+
const tx = this.encodeSettleTx(txId);
|
|
91
|
+
const receipt = await this.walletProvider.sendTransaction(tx);
|
|
92
|
+
if (!receipt.success) {
|
|
93
|
+
throw new Error(`release UserOp failed: ${receipt.hash}`);
|
|
94
|
+
}
|
|
95
|
+
return receipt;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validate release preconditions (state + dispute window).
|
|
99
|
+
*
|
|
100
|
+
* Handles both mock mode (disputeWindow = duration in seconds) and
|
|
101
|
+
* blockchain mode (disputeWindow = absolute timestamp). Uses a heuristic:
|
|
102
|
+
* values > 1 billion are absolute timestamps, smaller values are durations.
|
|
103
|
+
*
|
|
104
|
+
* @param txOrId - Transaction object or transaction ID to fetch
|
|
105
|
+
* @returns The validated transaction object (avoids double-fetch)
|
|
106
|
+
*/
|
|
107
|
+
async validateReleasePreconditions(txOrId) {
|
|
108
|
+
const tx = typeof txOrId === 'string'
|
|
109
|
+
? await this.runtime.getTransaction(txOrId)
|
|
110
|
+
: txOrId;
|
|
111
|
+
const txId = typeof txOrId === 'string' ? txOrId : txOrId.id;
|
|
112
|
+
if (!tx) {
|
|
113
|
+
throw new Error(`Transaction ${txId} not found`);
|
|
114
|
+
}
|
|
115
|
+
if (tx.state !== 'DELIVERED') {
|
|
116
|
+
throw new Error(`Cannot release escrow: transaction ${txId} is in state ${tx.state}, expected DELIVERED.`);
|
|
117
|
+
}
|
|
118
|
+
// Dispute window check.
|
|
119
|
+
// Requester is allowed to approve early release before dispute window end.
|
|
120
|
+
// Mock mode: completedAt = delivery timestamp, disputeWindow = duration in seconds.
|
|
121
|
+
// Blockchain mode: completedAt = 0 (V1), disputeWindow = absolute timestamp from chain.
|
|
122
|
+
// Heuristic: if disputeWindow > 1 billion, it's an absolute timestamp (post-2001).
|
|
123
|
+
if (tx.completedAt !== null && tx.completedAt !== undefined) {
|
|
124
|
+
const disputeWindowEnds = computeDisputeWindowEnds(tx.completedAt, tx.disputeWindow);
|
|
125
|
+
const now = this.runtime.time.now();
|
|
126
|
+
if (now < disputeWindowEnds) {
|
|
127
|
+
const caller = this.walletProvider.getAddress().toLowerCase();
|
|
128
|
+
const requester = tx.requester.toLowerCase();
|
|
129
|
+
const isRequester = caller === requester;
|
|
130
|
+
if (!isRequester) {
|
|
131
|
+
const remaining = disputeWindowEnds - now;
|
|
132
|
+
throw new Error(`Cannot release escrow: dispute window still active for transaction ${txId}. ` +
|
|
133
|
+
`Window expires in ${remaining} seconds.`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return tx;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Verify/require attestation for wallet-routed release calls.
|
|
141
|
+
*
|
|
142
|
+
* Includes txId cross-check to prevent attestation replay attacks:
|
|
143
|
+
* ensures the provided attestation belongs to the transaction being released.
|
|
144
|
+
*
|
|
145
|
+
* @param txId - Transaction ID being released
|
|
146
|
+
* @param attestationUID - Optional attestation UID
|
|
147
|
+
*/
|
|
148
|
+
async verifyReleaseAttestation(txId, attestationUID) {
|
|
149
|
+
const runtimeAny = this.runtime;
|
|
150
|
+
const runtimeSupportsAttestationFlag = typeof runtimeAny?.isAttestationRequired === 'function';
|
|
151
|
+
const attestationRequired = runtimeSupportsAttestationFlag
|
|
152
|
+
? Boolean(runtimeAny.isAttestationRequired())
|
|
153
|
+
: Boolean(this.easHelper);
|
|
154
|
+
if (attestationRequired && !attestationUID) {
|
|
155
|
+
throw new Error('Attestation verification is REQUIRED for escrow release. ' +
|
|
156
|
+
'Provide attestationUID when using Smart Wallet release.');
|
|
157
|
+
}
|
|
158
|
+
if (attestationRequired && !this.easHelper) {
|
|
159
|
+
throw new Error('Attestation verification is required but EAS helper is not initialized.');
|
|
160
|
+
}
|
|
161
|
+
if (attestationUID && this.easHelper) {
|
|
162
|
+
await this.easHelper.verifyAndRecordForRelease(txId, attestationUID);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Extract txId from escrowId, handling legacy format.
|
|
167
|
+
*
|
|
168
|
+
* @param escrowId - Escrow ID (may be txId or legacy "escrow-{txId}-{timestamp}" format)
|
|
169
|
+
* @returns The txId
|
|
170
|
+
*/
|
|
171
|
+
static extractTxId(escrowId) {
|
|
172
|
+
const legacyMatch = escrowId.match(/^escrow-(.+)-\d+$/);
|
|
173
|
+
return legacyMatch ? legacyMatch[1] : escrowId;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.SmartWalletRouter = SmartWalletRouter;
|
|
177
|
+
/**
|
|
178
|
+
* Compute the absolute end-time of the dispute window.
|
|
179
|
+
*
|
|
180
|
+
* Handles both representations transparently:
|
|
181
|
+
* - **Mock mode**: `disputeWindow` is a duration in seconds → `completedAt + disputeWindow`
|
|
182
|
+
* - **Blockchain mode**: `disputeWindow` is an absolute timestamp from on-chain → used as-is
|
|
183
|
+
*
|
|
184
|
+
* Heuristic: values > 1 billion are absolute timestamps (post-2001 epoch).
|
|
185
|
+
* Dispute window durations max at 30 days (~2.6M seconds). No overlap.
|
|
186
|
+
*
|
|
187
|
+
* @param completedAt - Delivery timestamp (0 in blockchain V1, real value in mock/V2)
|
|
188
|
+
* @param disputeWindow - Duration in seconds (mock) or absolute timestamp (blockchain)
|
|
189
|
+
* @returns Absolute timestamp when dispute window ends
|
|
190
|
+
*/
|
|
191
|
+
function computeDisputeWindowEnds(completedAt, disputeWindow) {
|
|
192
|
+
if (disputeWindow > ABSOLUTE_TIMESTAMP_THRESHOLD) {
|
|
193
|
+
// Blockchain mode: disputeWindow IS the absolute end timestamp
|
|
194
|
+
return disputeWindow;
|
|
195
|
+
}
|
|
196
|
+
// Mock mode: disputeWindow is a duration relative to completedAt
|
|
197
|
+
return completedAt + disputeWindow;
|
|
198
|
+
}
|
|
199
|
+
exports.computeDisputeWindowEnds = computeDisputeWindowEnds;
|
|
200
|
+
/**
|
|
201
|
+
* Factory function to create a SmartWalletRouter if wallet provider supports batching.
|
|
202
|
+
*
|
|
203
|
+
* @returns SmartWalletRouter instance if Smart Wallet is available, undefined otherwise
|
|
204
|
+
*/
|
|
205
|
+
function createSmartWalletRouter(walletProvider, contractAddresses, runtime, easHelper) {
|
|
206
|
+
if (walletProvider?.payACTPBatched && contractAddresses && runtime) {
|
|
207
|
+
return new SmartWalletRouter(walletProvider, contractAddresses, runtime, easHelper);
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
exports.createSmartWalletRouter = createSmartWalletRouter;
|
|
212
|
+
//# sourceMappingURL=SmartWalletRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmartWalletRouter.js","sourceRoot":"","sources":["../../src/wallet/SmartWalletRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export declare class DualNonceManager {
|
|
|
20
20
|
private readonly mutex;
|
|
21
21
|
/** Locally cached ACTP nonce — undefined means "re-read from chain" */
|
|
22
22
|
private cachedActpNonce;
|
|
23
|
+
/** Cached deployment block for ACTPKernel address */
|
|
24
|
+
private cachedKernelDeploymentBlock;
|
|
23
25
|
constructor(provider: ethers.JsonRpcProvider, senderAddress: string, actpKernelAddress: string);
|
|
24
26
|
/**
|
|
25
27
|
* Execute a callback while holding the nonce mutex.
|
|
@@ -52,5 +54,22 @@ export declare class DualNonceManager {
|
|
|
52
54
|
* Invalidate cached ACTP nonce (forces re-read on next operation).
|
|
53
55
|
*/
|
|
54
56
|
invalidateCache(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Override cached ACTP nonce.
|
|
59
|
+
*
|
|
60
|
+
* Used when caller deterministically advances nonce (e.g. retrying batched
|
|
61
|
+
* creation after "Escrow ID already used" simulation failures).
|
|
62
|
+
*/
|
|
63
|
+
setCachedActpNonce(nonce: bigint): void;
|
|
64
|
+
/**
|
|
65
|
+
* Find contract deployment block using binary search on getCode().
|
|
66
|
+
*/
|
|
67
|
+
private findContractDeploymentBlock;
|
|
68
|
+
/**
|
|
69
|
+
* Count TransactionCreated logs for requester in chunks.
|
|
70
|
+
*
|
|
71
|
+
* Chunking avoids RPC range limits on providers that reject very large log windows.
|
|
72
|
+
*/
|
|
73
|
+
private countRequesterTransactionCreatedEvents;
|
|
55
74
|
}
|
|
56
75
|
//# sourceMappingURL=DualNonceManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DualNonceManager.d.ts","sourceRoot":"","sources":["../../../src/wallet/aa/DualNonceManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"DualNonceManager.d.ts","sourceRoot":"","sources":["../../../src/wallet/aa/DualNonceManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAsDhC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAClD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,uEAAuE;IACvE,OAAO,CAAC,eAAe,CAAqB;IAC5C,qDAAqD;IACrD,OAAO,CAAC,2BAA2B,CAAqB;gBAGtD,QAAQ,EAAE,MAAM,CAAC,eAAe,EAChC,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM;IAO3B;;;;;;;;OAQG;IACG,OAAO,CAAC,CAAC,EACb,EAAE,EAAE,CAAC,MAAM,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;QACtE,MAAM,EAAE,CAAC,CAAC;QACV,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC,EACF,mBAAmB,GAAE,OAAc,GAClC,OAAO,CAAC,CAAC,CAAC;IA+Bb;;;OAGG;YACW,mBAAmB;IASjC;;;;OAIG;YACW,aAAa;IAgD3B;;OAEG;IACH,eAAe,IAAI,IAAI;IAIvB;;;;;OAKG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC;;OAEG;YACW,2BAA2B;IA2BzC;;;;OAIG;YACW,sCAAsC;CA0CrD"}
|
|
@@ -27,6 +27,9 @@ const ENTRYPOINT_NONCE_ABI = [
|
|
|
27
27
|
const ACTP_KERNEL_NONCE_ABI = [
|
|
28
28
|
'function requesterNonces(address requester) view returns (uint256)',
|
|
29
29
|
];
|
|
30
|
+
const TX_CREATED_EVENT_TOPIC = ethers_1.ethers.id('TransactionCreated(bytes32,address,address,uint256,bytes32,uint256,uint256,uint256)');
|
|
31
|
+
const INITIAL_LOG_CHUNK_SIZE = 200000;
|
|
32
|
+
const MIN_LOG_CHUNK_SIZE = 1000;
|
|
30
33
|
// ============================================================================
|
|
31
34
|
// Mutex
|
|
32
35
|
// ============================================================================
|
|
@@ -124,11 +127,32 @@ class DualNonceManager {
|
|
|
124
127
|
}
|
|
125
128
|
catch {
|
|
126
129
|
// Older ACTPKernel deployments don't expose requesterNonces.
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
Logger_1.sdkLogger.warn('requesterNonces not available on ACTPKernel —
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
// Derive nonce from TransactionCreated events for this requester.
|
|
131
|
+
// Uses deployment-block binary search + chunked logs (avoids block-0 scans).
|
|
132
|
+
Logger_1.sdkLogger.warn('requesterNonces not available on ACTPKernel — deriving nonce from events (older deployment?)');
|
|
133
|
+
try {
|
|
134
|
+
const latestBlock = await this.provider.getBlockNumber();
|
|
135
|
+
const deploymentBlock = await this.findContractDeploymentBlock(latestBlock);
|
|
136
|
+
const events = await this.countRequesterTransactionCreatedEvents(deploymentBlock, latestBlock);
|
|
137
|
+
const derivedNonce = BigInt(events.length);
|
|
138
|
+
Logger_1.sdkLogger.info('Derived ACTP nonce from TransactionCreated events', {
|
|
139
|
+
requester: this.senderAddress,
|
|
140
|
+
events: events.length,
|
|
141
|
+
fromBlock: deploymentBlock,
|
|
142
|
+
toBlock: latestBlock,
|
|
143
|
+
derivedNonce: derivedNonce.toString(),
|
|
144
|
+
});
|
|
145
|
+
this.cachedActpNonce = derivedNonce;
|
|
146
|
+
return derivedNonce;
|
|
147
|
+
}
|
|
148
|
+
catch (deriveError) {
|
|
149
|
+
// Last-resort fallback for very old/limited RPCs.
|
|
150
|
+
Logger_1.sdkLogger.warn('Could not derive ACTP nonce from events — using 0 as last resort', {
|
|
151
|
+
error: deriveError instanceof Error ? deriveError.message : String(deriveError),
|
|
152
|
+
});
|
|
153
|
+
this.cachedActpNonce = 0n;
|
|
154
|
+
return 0n;
|
|
155
|
+
}
|
|
132
156
|
}
|
|
133
157
|
}
|
|
134
158
|
/**
|
|
@@ -137,6 +161,77 @@ class DualNonceManager {
|
|
|
137
161
|
invalidateCache() {
|
|
138
162
|
this.cachedActpNonce = undefined;
|
|
139
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Override cached ACTP nonce.
|
|
166
|
+
*
|
|
167
|
+
* Used when caller deterministically advances nonce (e.g. retrying batched
|
|
168
|
+
* creation after "Escrow ID already used" simulation failures).
|
|
169
|
+
*/
|
|
170
|
+
setCachedActpNonce(nonce) {
|
|
171
|
+
this.cachedActpNonce = nonce;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Find contract deployment block using binary search on getCode().
|
|
175
|
+
*/
|
|
176
|
+
async findContractDeploymentBlock(latestBlock) {
|
|
177
|
+
if (this.cachedKernelDeploymentBlock !== undefined) {
|
|
178
|
+
return this.cachedKernelDeploymentBlock;
|
|
179
|
+
}
|
|
180
|
+
const codeAtLatest = await this.provider.getCode(this.actpKernelAddress, latestBlock);
|
|
181
|
+
if (codeAtLatest === '0x') {
|
|
182
|
+
throw new Error(`ACTPKernel has no code at latest block ${latestBlock}`);
|
|
183
|
+
}
|
|
184
|
+
let low = 0;
|
|
185
|
+
let high = latestBlock;
|
|
186
|
+
while (low < high) {
|
|
187
|
+
const mid = Math.floor((low + high) / 2);
|
|
188
|
+
const codeAtMid = await this.provider.getCode(this.actpKernelAddress, mid);
|
|
189
|
+
if (codeAtMid === '0x') {
|
|
190
|
+
low = mid + 1;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
high = mid;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
this.cachedKernelDeploymentBlock = low;
|
|
197
|
+
return low;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Count TransactionCreated logs for requester in chunks.
|
|
201
|
+
*
|
|
202
|
+
* Chunking avoids RPC range limits on providers that reject very large log windows.
|
|
203
|
+
*/
|
|
204
|
+
async countRequesterTransactionCreatedEvents(fromBlock, toBlock) {
|
|
205
|
+
const requesterTopic = ethers_1.ethers.zeroPadValue(this.senderAddress, 32).toLowerCase();
|
|
206
|
+
const logs = [];
|
|
207
|
+
let cursor = fromBlock;
|
|
208
|
+
let chunkSize = INITIAL_LOG_CHUNK_SIZE;
|
|
209
|
+
while (cursor <= toBlock) {
|
|
210
|
+
const chunkEnd = Math.min(cursor + chunkSize - 1, toBlock);
|
|
211
|
+
try {
|
|
212
|
+
const chunkLogs = await this.provider.getLogs({
|
|
213
|
+
address: this.actpKernelAddress,
|
|
214
|
+
topics: [TX_CREATED_EVENT_TOPIC, null, requesterTopic],
|
|
215
|
+
fromBlock: cursor,
|
|
216
|
+
toBlock: chunkEnd,
|
|
217
|
+
});
|
|
218
|
+
logs.push(...chunkLogs);
|
|
219
|
+
cursor = chunkEnd + 1;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (chunkSize <= MIN_LOG_CHUNK_SIZE) {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
chunkSize = Math.max(MIN_LOG_CHUNK_SIZE, Math.floor(chunkSize / 2));
|
|
226
|
+
Logger_1.sdkLogger.warn('TransactionCreated log scan range too large; reducing chunk size while deriving ACTP nonce', {
|
|
227
|
+
nextChunkSize: chunkSize,
|
|
228
|
+
fromBlock: cursor,
|
|
229
|
+
attemptedToBlock: chunkEnd,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return logs;
|
|
234
|
+
}
|
|
140
235
|
}
|
|
141
236
|
exports.DualNonceManager = DualNonceManager;
|
|
142
237
|
//# sourceMappingURL=DualNonceManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DualNonceManager.js","sourceRoot":"","sources":["../../../src/wallet/aa/DualNonceManager.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAEH,mCAAgC;AAChC,2CAA6C;AAC7C,+CAA+C;AAE/C,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,MAAM,oBAAoB,GAAG;IAC3B,uEAAuE;CACxE,CAAC;AAEF,MAAM,qBAAqB,GAAG;IAC5B,oEAAoE;CACrE,CAAC;AAEF,+EAA+E;AAC/E,QAAQ;AACR,+EAA+E;AAE/E,MAAM,KAAK;IAAX;QACU,WAAM,GAAG,KAAK,CAAC;QACf,UAAK,GAAmB,EAAE,CAAC;IAoBrC,CAAC;IAlBC,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,OAAO;QACT,CAAC;QACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YACjC,IAAI,EAAE,CAAC;QACT,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;CACF;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,MAAa,gBAAgB;
|
|
1
|
+
{"version":3,"file":"DualNonceManager.js","sourceRoot":"","sources":["../../../src/wallet/aa/DualNonceManager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agirails/sdk",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.4",
|
|
4
4
|
"description": "AGIRAILS SDK for the ACTP (Agent Commerce Transaction Protocol) - Unified mock + blockchain support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,9 +21,6 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
|
-
"src",
|
|
25
|
-
"!src/**/*.test.ts",
|
|
26
|
-
"!src/**/*.spec.ts",
|
|
27
24
|
"bin",
|
|
28
25
|
"README.md",
|
|
29
26
|
"LICENSE"
|
|
@@ -36,7 +33,7 @@
|
|
|
36
33
|
"test:onchain": "hardhat test",
|
|
37
34
|
"lint": "eslint src --ext .ts",
|
|
38
35
|
"format": "prettier --write 'src/**/*.ts'",
|
|
39
|
-
"prepublishOnly": "npm run build && npm test",
|
|
36
|
+
"prepublishOnly": "npm run build && npm test && npm run lint",
|
|
40
37
|
"test:setup": "ts-node test-scripts/00-setup.ts",
|
|
41
38
|
"test:happy-path": "ts-node test-scripts/01-happy-path.ts",
|
|
42
39
|
"test:dispute": "ts-node test-scripts/02-dispute.ts",
|
|
@@ -80,7 +77,7 @@
|
|
|
80
77
|
"ethers": "6.15.0",
|
|
81
78
|
"ethr-did-resolver": "11.0.5",
|
|
82
79
|
"fast-json-stable-stringify": "2.1.0",
|
|
83
|
-
"kubo-rpc-client": "
|
|
80
|
+
"kubo-rpc-client": "6.1.0",
|
|
84
81
|
"proper-lockfile": "4.1.2",
|
|
85
82
|
"yaml": "^2.8.2",
|
|
86
83
|
"zod": "^3.22.4"
|