@haven_ai/sdk 0.1.28-alpha.0 → 0.1.30-alpha.0
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 +1 -1
- package/dist/index.cjs +33 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -3
- package/dist/index.d.ts +74 -3
- package/dist/index.js +33 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ approval if it exceeds it), and shows up in your Haven dashboard activity feed.
|
|
|
68
68
|
- On-chain Safe AllowanceModule state enforces the agent budget.
|
|
69
69
|
- `getAllowances()` / `get_allowances` is the right path for budget, remaining amount, reset period, or "what can I spend?" questions.
|
|
70
70
|
- If an API key is exposed or lost, rotate it from the Haven agent detail page. The new key is shown once and the old key stops working.
|
|
71
|
-
- If a delegate key is exposed or lost,
|
|
71
|
+
- If a delegate key is exposed or lost, a delegation-rail agent is **re-keyed** rather than replaced — same agent, new signing key, budget remainder carried. See [Replacing an agent's signing key](../../docs/product/agent-key-rotation.md). Legacy AllowanceModule agents are paused or revoked and re-onboarded instead.
|
|
72
72
|
|
|
73
73
|
## Step-by-Step API
|
|
74
74
|
|
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,7 @@ var accounts = require('viem/accounts');
|
|
|
10
10
|
// src/client.ts
|
|
11
11
|
|
|
12
12
|
// src/types.ts
|
|
13
|
+
var DEFAULT_CONFIRMATION_TIMEOUT_MS = 9e4;
|
|
13
14
|
var AgentPaymentPhase = {
|
|
14
15
|
/** The agent must sign and submit the prepared payment before Haven can relay it. */
|
|
15
16
|
AgentSignatureRequired: "agent_signature_required",
|
|
@@ -761,7 +762,7 @@ function x402AuthorizationAmount(option) {
|
|
|
761
762
|
return amount;
|
|
762
763
|
}
|
|
763
764
|
function buildX402ExpectedMessage(context) {
|
|
764
|
-
const version = context.typedDataHash ? 2 : 1;
|
|
765
|
+
const version = context.payerDelegate ? 3 : context.typedDataHash ? 2 : 1;
|
|
765
766
|
const payload = {
|
|
766
767
|
version,
|
|
767
768
|
kind: "haven.x402.expected",
|
|
@@ -779,6 +780,12 @@ function buildX402ExpectedMessage(context) {
|
|
|
779
780
|
if (context.typedDataHash) {
|
|
780
781
|
payload.typedDataHash = context.typedDataHash.toLowerCase();
|
|
781
782
|
}
|
|
783
|
+
if (context.payerDelegate) {
|
|
784
|
+
payload.payerDelegate = context.payerDelegate.toLowerCase();
|
|
785
|
+
if (context.payerAgentId) {
|
|
786
|
+
payload.payerAgentId = context.payerAgentId;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
782
789
|
return `Haven x402 expected context v${version}
|
|
783
790
|
${stableStringify2(payload)}`;
|
|
784
791
|
}
|
|
@@ -1627,6 +1634,20 @@ function createErc20Contract(address, abi, runner) {
|
|
|
1627
1634
|
}
|
|
1628
1635
|
|
|
1629
1636
|
// src/delegate-sweep.ts
|
|
1637
|
+
function isWaitTimeout(err) {
|
|
1638
|
+
return err?.code === "TIMEOUT";
|
|
1639
|
+
}
|
|
1640
|
+
async function waitForSweepTx(tx) {
|
|
1641
|
+
let receipt;
|
|
1642
|
+
try {
|
|
1643
|
+
receipt = await tx.wait(1, DEFAULT_CONFIRMATION_TIMEOUT_MS);
|
|
1644
|
+
} catch (err) {
|
|
1645
|
+
if (!isWaitTimeout(err)) throw err;
|
|
1646
|
+
return { txHash: tx.hash, confirmation: "unconfirmed" };
|
|
1647
|
+
}
|
|
1648
|
+
if (!receipt) return { txHash: tx.hash, confirmation: "unconfirmed" };
|
|
1649
|
+
return { txHash: receipt.hash, confirmation: "confirmed" };
|
|
1650
|
+
}
|
|
1630
1651
|
var DelegateSweepApi = class {
|
|
1631
1652
|
constructor(options) {
|
|
1632
1653
|
this.options = options;
|
|
@@ -1646,9 +1667,8 @@ var DelegateSweepApi = class {
|
|
|
1646
1667
|
const balance2 = await contract.balanceOf(agent.delegateAddress);
|
|
1647
1668
|
if (balance2 > 0n) {
|
|
1648
1669
|
const tx = await contract.transfer(agent.safeAddress, balance2);
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1651
|
-
transfers.push({ asset: "USDC", amount: format(balance2, 6), amountAtomic: balance2.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash) });
|
|
1670
|
+
const { txHash, confirmation } = await waitForSweepTx(tx);
|
|
1671
|
+
transfers.push({ asset: "USDC", amount: format(balance2, 6), amountAtomic: balance2.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash), confirmation });
|
|
1652
1672
|
}
|
|
1653
1673
|
}
|
|
1654
1674
|
const balance = await provider.getBalance(agent.delegateAddress);
|
|
@@ -1657,12 +1677,11 @@ var DelegateSweepApi = class {
|
|
|
1657
1677
|
const send = balance - (fee.maxFeePerGas ?? fee.gasPrice ?? 1000000n) * 21000n * 2n;
|
|
1658
1678
|
if (send > 0n) {
|
|
1659
1679
|
const tx = await wallet.sendTransaction({ to: agent.safeAddress, value: send });
|
|
1660
|
-
const
|
|
1661
|
-
|
|
1662
|
-
transfers.push({ asset: "ETH", amount: format(send, 18), amountAtomic: send.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash) });
|
|
1680
|
+
const { txHash, confirmation } = await waitForSweepTx(tx);
|
|
1681
|
+
transfers.push({ asset: "ETH", amount: format(send, 18), amountAtomic: send.toString(), txHash, explorerUrl: this.options.buildExplorerUrl(agent.chainId, txHash), confirmation });
|
|
1663
1682
|
}
|
|
1664
1683
|
}
|
|
1665
|
-
return { fromAddress: agent.delegateAddress, toAddress: agent.safeAddress, chainId: agent.chainId, transfers };
|
|
1684
|
+
return { fromAddress: agent.delegateAddress, toAddress: agent.safeAddress, chainId: agent.chainId, transfers, unconfirmed: transfers.some((t) => t.confirmation === "unconfirmed") };
|
|
1666
1685
|
}
|
|
1667
1686
|
prepareSweep() {
|
|
1668
1687
|
return this.options.transport.post("/machine-payments/sweep/prepare", {});
|
|
@@ -2639,7 +2658,6 @@ function parseProtocolReceiptHeader(value) {
|
|
|
2639
2658
|
}
|
|
2640
2659
|
|
|
2641
2660
|
// src/client.ts
|
|
2642
|
-
var DEFAULT_CONFIRMATION_TIMEOUT = 9e4;
|
|
2643
2661
|
var DEFAULT_POLLING_INTERVAL = 3e3;
|
|
2644
2662
|
function x402TypedDataDigest(typedData) {
|
|
2645
2663
|
if (!typedData || typeof typedData !== "object") return void 0;
|
|
@@ -2714,7 +2732,7 @@ var HavenClient = class {
|
|
|
2714
2732
|
});
|
|
2715
2733
|
this.x402Wallet = config.x402Wallet;
|
|
2716
2734
|
this.merchantTransport = new McpMerchantTransport({ merchantTimeout: config.merchantTimeout });
|
|
2717
|
-
this.confirmationTimeout = config.confirmationTimeout ??
|
|
2735
|
+
this.confirmationTimeout = config.confirmationTimeout ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
2718
2736
|
this.pollingInterval = config.pollingInterval ?? DEFAULT_POLLING_INTERVAL;
|
|
2719
2737
|
this.chainRpcs = config.chainRpcs ?? {};
|
|
2720
2738
|
if (this.delegateKey) {
|
|
@@ -2885,6 +2903,8 @@ var HavenClient = class {
|
|
|
2885
2903
|
asset: option.asset,
|
|
2886
2904
|
network: option.network,
|
|
2887
2905
|
expectedAuth: raw.x402_expected_auth,
|
|
2906
|
+
payerDelegate: raw.payer_delegate,
|
|
2907
|
+
payerAgentId: raw.payer_agent_id,
|
|
2888
2908
|
// #1138: the digest the delegation-rail expected context commits to.
|
|
2889
2909
|
// Re-derived locally, exactly like every other context field the edge
|
|
2890
2910
|
// signer is handed (amount, merchantTo, …) — none of them are trusted
|
|
@@ -3779,8 +3799,8 @@ var toolDescriptions = {
|
|
|
3779
3799
|
sweep_delegate: {
|
|
3780
3800
|
summary: "Sweep stranded USDC and/or ETH from the delegate wallet back to the originating Safe.",
|
|
3781
3801
|
selectionGuidance: "Use this when the user instructs you to recover stranded funds on the delegate wallet, or when a payment status returns nextAction=sweep_stranded_funds. Do NOT use for normal payments \u2014 use haven_pay_x402. Do NOT use to read balances only \u2014 use haven_get_allowances.",
|
|
3782
|
-
behavior:
|
|
3783
|
-
nextActionGuidance:
|
|
3802
|
+
behavior: `Reads the delegate EOA's on-chain USDC and ETH balances. For each non-zero balance, signs and submits a transfer from the delegate EOA to the originating Safe (hardcoded destination). The delegate key signs locally \u2014 Haven never sees it and the backend never constructs signed transactions (CASP/MiCA Red Line #2). Returns tx hashes and recovered amounts. Returns an empty transfers list when nothing is stranded. Each transfer carries confirmation: "confirmed" (a receipt was seen \u2014 the funds are in the Safe) or "unconfirmed" (broadcast but not confirmed within 90 seconds \u2014 still in the mempool, may still land). The top-level unconfirmed flag is true when any transfer is unconfirmed.`,
|
|
3803
|
+
nextActionGuidance: 'If transfers is non-empty, confirm the amounts with the user. Report a transfer as recovered ONLY when its confirmation is "confirmed". For an "unconfirmed" transfer, tell the user it was submitted but not yet confirmed, give them its txHash and explorerUrl to check, and do not re-run the sweep immediately \u2014 a re-run after it lands will simply find nothing stranded.'
|
|
3784
3804
|
},
|
|
3785
3805
|
send: {
|
|
3786
3806
|
summary: "Send ETH or USDC directly from the agent's Haven wallet to a recipient address.",
|
|
@@ -4309,6 +4329,7 @@ exports.AgentPaymentRail = AgentPaymentRail;
|
|
|
4309
4329
|
exports.AgentPaymentRailDescriptions = AgentPaymentRailDescriptions;
|
|
4310
4330
|
exports.AgentPaymentRailSchema = AgentPaymentRailSchema;
|
|
4311
4331
|
exports.AgentPaymentWarningCode = AgentPaymentWarningCode;
|
|
4332
|
+
exports.DEFAULT_CONFIRMATION_TIMEOUT_MS = DEFAULT_CONFIRMATION_TIMEOUT_MS;
|
|
4312
4333
|
exports.DISCOVERY_MAX_BYTES = DISCOVERY_MAX_BYTES;
|
|
4313
4334
|
exports.ERC7710_ASSET_TRANSFER_METHOD = ERC7710_ASSET_TRANSFER_METHOD;
|
|
4314
4335
|
exports.HAVEN_MINIMUM_NODE_VERSION = HAVEN_MINIMUM_NODE_VERSION;
|