@oobe-protocol-labs/synapse-sap-sdk 0.11.0 → 0.12.5
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/cjs/constants/payments.js +51 -1
- package/dist/cjs/constants/payments.js.map +1 -1
- package/dist/cjs/idl/synapse_agent_sap.json +156 -4
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/modules/escrow-v2.js +46 -0
- package/dist/cjs/modules/escrow-v2.js.map +1 -1
- package/dist/cjs/modules/escrow.js +13 -3
- package/dist/cjs/modules/escrow.js.map +1 -1
- package/dist/cjs/modules/receipt.js +4 -0
- package/dist/cjs/modules/receipt.js.map +1 -1
- package/dist/cjs/modules/staking.js +30 -0
- package/dist/cjs/modules/staking.js.map +1 -1
- package/dist/cjs/registries/x402.js +10 -4
- package/dist/cjs/registries/x402.js.map +1 -1
- package/dist/cjs/utils/index.js +2 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/priority-fee.js +52 -0
- package/dist/cjs/utils/priority-fee.js.map +1 -1
- package/dist/esm/constants/payments.js +49 -0
- package/dist/esm/constants/payments.js.map +1 -1
- package/dist/esm/idl/synapse_agent_sap.json +156 -4
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/modules/escrow-v2.js +47 -1
- package/dist/esm/modules/escrow-v2.js.map +1 -1
- package/dist/esm/modules/escrow.js +14 -4
- package/dist/esm/modules/escrow.js.map +1 -1
- package/dist/esm/modules/receipt.js +5 -1
- package/dist/esm/modules/receipt.js.map +1 -1
- package/dist/esm/modules/staking.js +30 -0
- package/dist/esm/modules/staking.js.map +1 -1
- package/dist/esm/registries/x402.js +11 -5
- package/dist/esm/registries/x402.js.map +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/priority-fee.js +51 -0
- package/dist/esm/utils/priority-fee.js.map +1 -1
- package/dist/types/constants/payments.d.ts +43 -0
- package/dist/types/constants/payments.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modules/escrow-v2.d.ts.map +1 -1
- package/dist/types/modules/escrow.d.ts.map +1 -1
- package/dist/types/modules/receipt.d.ts.map +1 -1
- package/dist/types/modules/staking.d.ts +19 -0
- package/dist/types/modules/staking.d.ts.map +1 -1
- package/dist/types/registries/x402.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/priority-fee.d.ts +20 -0
- package/dist/types/utils/priority-fee.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants/payments.ts +53 -0
- package/src/idl/synapse_agent_sap.json +156 -4
- package/src/index.ts +1 -0
- package/src/modules/escrow-v2.ts +49 -1
- package/src/modules/escrow.ts +14 -3
- package/src/modules/receipt.ts +5 -0
- package/src/modules/staking.ts +35 -0
- package/src/registries/x402.ts +11 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/priority-fee.ts +55 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"priority-fee.d.ts","sourceRoot":"","sources":["../../../src/utils/priority-fee.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,iBAAiB,CAAC;AAMzB;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,SAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"priority-fee.d.ts","sourceRoot":"","sources":["../../../src/utils/priority-fee.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,iBAAiB,CAAC;AAMzB;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,SAAU,CAAC;AA8B1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAM/D;AAMD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAE3C;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAE9D;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAMD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,aAAa,CAKtD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,aAAa,CAK5D,CAAC;AAMH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,CAAC,EAAE,iBAAiB,GACzB,sBAAsB,EAAE,CAwB1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,IAAI,CAAC,EAAE,aAAa,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAgBrC"}
|
package/package.json
CHANGED
|
@@ -55,6 +55,59 @@ export const USDC_MINT_DEVNET = new PublicKey(
|
|
|
55
55
|
*/
|
|
56
56
|
export const MIN_AGENT_STAKE_LAMPORTS = BigInt(100_000_000);
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Slash share applied on a lost dispute, in basis points.
|
|
60
|
+
* Mirrors `AgentStake::SLASH_BPS` on-chain (`5_000` = 50%).
|
|
61
|
+
*
|
|
62
|
+
* @name SLASH_BPS
|
|
63
|
+
* @category Constants
|
|
64
|
+
* @since v0.11.0
|
|
65
|
+
*/
|
|
66
|
+
export const SLASH_BPS = 5_000n;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Stake coverage ratio enforced at `createEscrowV2` (basis points).
|
|
70
|
+
* Mirrors `AgentStake::STAKE_COVERAGE_BPS` on-chain. Currently equal to
|
|
71
|
+
* {@link SLASH_BPS} so the slash on a lost dispute is fully collateralised.
|
|
72
|
+
*
|
|
73
|
+
* @name STAKE_COVERAGE_BPS
|
|
74
|
+
* @category Constants
|
|
75
|
+
* @since v0.11.0
|
|
76
|
+
*/
|
|
77
|
+
export const STAKE_COVERAGE_BPS = SLASH_BPS;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Unstake cooldown in seconds. Mirrors `AgentStake::UNSTAKE_COOLDOWN_SECONDS`
|
|
81
|
+
* on-chain (`604_800` = 7 days). Replaces the misnamed pre-v0.11
|
|
82
|
+
* `UNSTAKE_COOLDOWN_SLOTS` constant which was never used by handlers.
|
|
83
|
+
*
|
|
84
|
+
* @name UNSTAKE_COOLDOWN_SECONDS
|
|
85
|
+
* @category Constants
|
|
86
|
+
* @since v0.11.0
|
|
87
|
+
*/
|
|
88
|
+
export const UNSTAKE_COOLDOWN_SECONDS = 604_800;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Required `staked_amount` (lamports) for an agent to accept an escrow of
|
|
92
|
+
* `escrowLamports`. Equal to `max(MIN_AGENT_STAKE_LAMPORTS,
|
|
93
|
+
* escrowLamports * STAKE_COVERAGE_BPS / 10_000)`.
|
|
94
|
+
*
|
|
95
|
+
* Mirrors the on-chain check enforced in `create_escrow_v2` (v0.11 H-1).
|
|
96
|
+
* Use this to preflight an escrow create call and surface an actionable
|
|
97
|
+
* error before paying tx fees.
|
|
98
|
+
*
|
|
99
|
+
* @name computeRequiredStakeLamports
|
|
100
|
+
* @category Constants
|
|
101
|
+
* @since v0.11.0
|
|
102
|
+
*/
|
|
103
|
+
export function computeRequiredStakeLamports(escrowLamports: bigint): bigint {
|
|
104
|
+
if (escrowLamports < 0n) {
|
|
105
|
+
throw new RangeError("escrowLamports must be ≥ 0");
|
|
106
|
+
}
|
|
107
|
+
const coverage = (escrowLamports * STAKE_COVERAGE_BPS) / 10_000n;
|
|
108
|
+
return coverage > MIN_AGENT_STAKE_LAMPORTS ? coverage : MIN_AGENT_STAKE_LAMPORTS;
|
|
109
|
+
}
|
|
110
|
+
|
|
58
111
|
/**
|
|
59
112
|
* Maximum delegate duration (seconds) accepted by `add_vault_delegate`.
|
|
60
113
|
* Mirrors `VaultDelegate::MAX_DELEGATE_DURATION_SECS` on-chain
|
|
@@ -598,6 +598,38 @@
|
|
|
598
598
|
}
|
|
599
599
|
]
|
|
600
600
|
}
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"name": "agent_stake",
|
|
604
|
+
"docs": [
|
|
605
|
+
"v0.11 H-3: AgentStake is now a typed required account so the slash on",
|
|
606
|
+
"DepositorWins outcomes is guaranteed instead of silently skipped when",
|
|
607
|
+
"the caller forgets to pass it via remaining_accounts."
|
|
608
|
+
],
|
|
609
|
+
"writable": true,
|
|
610
|
+
"pda": {
|
|
611
|
+
"seeds": [
|
|
612
|
+
{
|
|
613
|
+
"kind": "const",
|
|
614
|
+
"value": [
|
|
615
|
+
115,
|
|
616
|
+
97,
|
|
617
|
+
112,
|
|
618
|
+
95,
|
|
619
|
+
115,
|
|
620
|
+
116,
|
|
621
|
+
97,
|
|
622
|
+
107,
|
|
623
|
+
101
|
|
624
|
+
]
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
"kind": "account",
|
|
628
|
+
"path": "escrow.agent",
|
|
629
|
+
"account": "EscrowAccountV2"
|
|
630
|
+
}
|
|
631
|
+
]
|
|
632
|
+
}
|
|
601
633
|
}
|
|
602
634
|
],
|
|
603
635
|
"args": []
|
|
@@ -2504,10 +2536,16 @@
|
|
|
2504
2536
|
{
|
|
2505
2537
|
"name": "wallet",
|
|
2506
2538
|
"writable": true,
|
|
2507
|
-
"signer": true
|
|
2539
|
+
"signer": true,
|
|
2540
|
+
"relations": [
|
|
2541
|
+
"agent"
|
|
2542
|
+
]
|
|
2508
2543
|
},
|
|
2509
2544
|
{
|
|
2510
2545
|
"name": "agent",
|
|
2546
|
+
"docs": [
|
|
2547
|
+
"v0.11 M-2: typed agent account."
|
|
2548
|
+
],
|
|
2511
2549
|
"pda": {
|
|
2512
2550
|
"seeds": [
|
|
2513
2551
|
{
|
|
@@ -3647,10 +3685,16 @@
|
|
|
3647
3685
|
{
|
|
3648
3686
|
"name": "wallet",
|
|
3649
3687
|
"writable": true,
|
|
3650
|
-
"signer": true
|
|
3688
|
+
"signer": true,
|
|
3689
|
+
"relations": [
|
|
3690
|
+
"agent"
|
|
3691
|
+
]
|
|
3651
3692
|
},
|
|
3652
3693
|
{
|
|
3653
3694
|
"name": "agent",
|
|
3695
|
+
"docs": [
|
|
3696
|
+
"v0.11 M-2: typed agent account."
|
|
3697
|
+
],
|
|
3654
3698
|
"pda": {
|
|
3655
3699
|
"seeds": [
|
|
3656
3700
|
{
|
|
@@ -4671,10 +4715,16 @@
|
|
|
4671
4715
|
{
|
|
4672
4716
|
"name": "wallet",
|
|
4673
4717
|
"writable": true,
|
|
4674
|
-
"signer": true
|
|
4718
|
+
"signer": true,
|
|
4719
|
+
"relations": [
|
|
4720
|
+
"agent"
|
|
4721
|
+
]
|
|
4675
4722
|
},
|
|
4676
4723
|
{
|
|
4677
4724
|
"name": "agent",
|
|
4725
|
+
"docs": [
|
|
4726
|
+
"v0.11 M-2: typed agent account — stake cannot be opened for a non-existent agent."
|
|
4727
|
+
],
|
|
4678
4728
|
"pda": {
|
|
4679
4729
|
"seeds": [
|
|
4680
4730
|
{
|
|
@@ -6476,10 +6526,16 @@
|
|
|
6476
6526
|
"accounts": [
|
|
6477
6527
|
{
|
|
6478
6528
|
"name": "wallet",
|
|
6479
|
-
"signer": true
|
|
6529
|
+
"signer": true,
|
|
6530
|
+
"relations": [
|
|
6531
|
+
"agent"
|
|
6532
|
+
]
|
|
6480
6533
|
},
|
|
6481
6534
|
{
|
|
6482
6535
|
"name": "agent",
|
|
6536
|
+
"docs": [
|
|
6537
|
+
"v0.11 M-2: typed agent account."
|
|
6538
|
+
],
|
|
6483
6539
|
"pda": {
|
|
6484
6540
|
"seeds": [
|
|
6485
6541
|
{
|
|
@@ -9256,6 +9312,19 @@
|
|
|
9256
9312
|
198
|
|
9257
9313
|
]
|
|
9258
9314
|
},
|
|
9315
|
+
{
|
|
9316
|
+
"name": "StakeClosedEvent",
|
|
9317
|
+
"discriminator": [
|
|
9318
|
+
212,
|
|
9319
|
+
204,
|
|
9320
|
+
207,
|
|
9321
|
+
181,
|
|
9322
|
+
185,
|
|
9323
|
+
249,
|
|
9324
|
+
134,
|
|
9325
|
+
59
|
|
9326
|
+
]
|
|
9327
|
+
},
|
|
9259
9328
|
{
|
|
9260
9329
|
"name": "StakeDepositedEvent",
|
|
9261
9330
|
"discriminator": [
|
|
@@ -9412,6 +9481,19 @@
|
|
|
9412
9481
|
57
|
|
9413
9482
|
]
|
|
9414
9483
|
},
|
|
9484
|
+
{
|
|
9485
|
+
"name": "UnstakeCancelledEvent",
|
|
9486
|
+
"discriminator": [
|
|
9487
|
+
57,
|
|
9488
|
+
228,
|
|
9489
|
+
7,
|
|
9490
|
+
42,
|
|
9491
|
+
227,
|
|
9492
|
+
64,
|
|
9493
|
+
93,
|
|
9494
|
+
51
|
|
9495
|
+
]
|
|
9496
|
+
},
|
|
9415
9497
|
{
|
|
9416
9498
|
"name": "UnstakeCompletedEvent",
|
|
9417
9499
|
"discriminator": [
|
|
@@ -10211,6 +10293,21 @@
|
|
|
10211
10293
|
"code": 6143,
|
|
10212
10294
|
"name": "DuplicateServiceHash",
|
|
10213
10295
|
"msg": "dup service hash"
|
|
10296
|
+
},
|
|
10297
|
+
{
|
|
10298
|
+
"code": 6144,
|
|
10299
|
+
"name": "StakeBelowCoverage",
|
|
10300
|
+
"msg": "stake under coverage"
|
|
10301
|
+
},
|
|
10302
|
+
{
|
|
10303
|
+
"code": 6145,
|
|
10304
|
+
"name": "StakeNotClosable",
|
|
10305
|
+
"msg": "stake not closable"
|
|
10306
|
+
},
|
|
10307
|
+
{
|
|
10308
|
+
"code": 6146,
|
|
10309
|
+
"name": "AgentStakeAccountMissing",
|
|
10310
|
+
"msg": "agent stake account missing"
|
|
10214
10311
|
}
|
|
10215
10312
|
],
|
|
10216
10313
|
"types": [
|
|
@@ -13436,6 +13533,33 @@
|
|
|
13436
13533
|
]
|
|
13437
13534
|
}
|
|
13438
13535
|
},
|
|
13536
|
+
{
|
|
13537
|
+
"name": "StakeClosedEvent",
|
|
13538
|
+
"docs": [
|
|
13539
|
+
"v0.11 L-3: emitted when an agent's stake account is closed and rent reclaimed."
|
|
13540
|
+
],
|
|
13541
|
+
"type": {
|
|
13542
|
+
"kind": "struct",
|
|
13543
|
+
"fields": [
|
|
13544
|
+
{
|
|
13545
|
+
"name": "agent",
|
|
13546
|
+
"type": "pubkey"
|
|
13547
|
+
},
|
|
13548
|
+
{
|
|
13549
|
+
"name": "wallet",
|
|
13550
|
+
"type": "pubkey"
|
|
13551
|
+
},
|
|
13552
|
+
{
|
|
13553
|
+
"name": "returned_lamports",
|
|
13554
|
+
"type": "u64"
|
|
13555
|
+
},
|
|
13556
|
+
{
|
|
13557
|
+
"name": "timestamp",
|
|
13558
|
+
"type": "i64"
|
|
13559
|
+
}
|
|
13560
|
+
]
|
|
13561
|
+
}
|
|
13562
|
+
},
|
|
13439
13563
|
{
|
|
13440
13564
|
"name": "StakeDepositedEvent",
|
|
13441
13565
|
"docs": [
|
|
@@ -14196,6 +14320,34 @@
|
|
|
14196
14320
|
]
|
|
14197
14321
|
}
|
|
14198
14322
|
},
|
|
14323
|
+
{
|
|
14324
|
+
"name": "UnstakeCancelledEvent",
|
|
14325
|
+
"docs": [
|
|
14326
|
+
"v0.11 L-2: emitted when a `deposit_stake` clears a previously requested",
|
|
14327
|
+
"unstake (top-up = implicit cancel of the pending withdrawal)."
|
|
14328
|
+
],
|
|
14329
|
+
"type": {
|
|
14330
|
+
"kind": "struct",
|
|
14331
|
+
"fields": [
|
|
14332
|
+
{
|
|
14333
|
+
"name": "agent",
|
|
14334
|
+
"type": "pubkey"
|
|
14335
|
+
},
|
|
14336
|
+
{
|
|
14337
|
+
"name": "wallet",
|
|
14338
|
+
"type": "pubkey"
|
|
14339
|
+
},
|
|
14340
|
+
{
|
|
14341
|
+
"name": "cancelled_amount",
|
|
14342
|
+
"type": "u64"
|
|
14343
|
+
},
|
|
14344
|
+
{
|
|
14345
|
+
"name": "timestamp",
|
|
14346
|
+
"type": "i64"
|
|
14347
|
+
}
|
|
14348
|
+
]
|
|
14349
|
+
}
|
|
14350
|
+
},
|
|
14199
14351
|
{
|
|
14200
14352
|
"name": "UnstakeCompletedEvent",
|
|
14201
14353
|
"docs": [
|
package/src/index.ts
CHANGED
package/src/modules/escrow-v2.ts
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
buildRpcOptions,
|
|
38
38
|
} from "../utils/priority-fee";
|
|
39
39
|
import type { SettleOptions } from "../utils/priority-fee";
|
|
40
|
-
import { isAcceptedPaymentToken } from "../constants/payments";
|
|
40
|
+
import { isAcceptedPaymentToken, computeRequiredStakeLamports } from "../constants/payments";
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* @name EscrowV2Module
|
|
@@ -97,6 +97,54 @@ export class EscrowV2Module extends BaseModule {
|
|
|
97
97
|
const [agentPda] = deriveAgent(agentWallet);
|
|
98
98
|
const [escrowPda] = this.deriveEscrow(agentPda, undefined, args.escrowNonce);
|
|
99
99
|
const [stakePda] = deriveStake(agentPda);
|
|
100
|
+
// v0.11 H-1 preflight: surface an actionable error if the agent's stake
|
|
101
|
+
// does not cover the slashable share of the new escrow. Saves a failed
|
|
102
|
+
// tx fee and gives the caller a clear top-up amount.
|
|
103
|
+
try {
|
|
104
|
+
const stakeAccount = await this.fetchAccountNullable<{ stakedAmount: BN }>("agentStake", stakePda);
|
|
105
|
+
if (stakeAccount) {
|
|
106
|
+
const escrowLamports = BigInt(this.bn(args.initialDeposit).toString());
|
|
107
|
+
const required = computeRequiredStakeLamports(escrowLamports);
|
|
108
|
+
const have = BigInt(stakeAccount.stakedAmount.toString());
|
|
109
|
+
if (have < required) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`createEscrowV2: agent stake ${have} lamports < required ${required} ` +
|
|
112
|
+
`lamports for escrow of ${escrowLamports} lamports. Top up via stakingModule.deposit.`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// If no stake account exists at all, on-chain will reject with
|
|
117
|
+
// AccountNotInitialized — we let that bubble up unchanged.
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// Preflight is advisory; rethrow only the explicit coverage error.
|
|
120
|
+
if (err instanceof Error && err.message.startsWith("createEscrowV2: agent stake")) {
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// v0.11 H-1 preflight: surface an actionable error if the agent's stake
|
|
125
|
+
// does not cover the slashable share of the new escrow. Saves a failed
|
|
126
|
+
// tx fee and gives the caller a clear top-up amount.
|
|
127
|
+
try {
|
|
128
|
+
const stakeAccount = await this.fetchAccountNullable<{ stakedAmount: BN }>("agentStake", stakePda);
|
|
129
|
+
if (stakeAccount) {
|
|
130
|
+
const escrowLamports = BigInt(this.bn(args.initialDeposit).toString());
|
|
131
|
+
const required = computeRequiredStakeLamports(escrowLamports);
|
|
132
|
+
const have = BigInt(stakeAccount.stakedAmount.toString());
|
|
133
|
+
if (have < required) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`createEscrowV2: agent stake ${have} lamports < required ${required} ` +
|
|
136
|
+
`lamports for escrow of ${escrowLamports} lamports. Top up via stakingModule.deposit.`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// If no stake account exists at all, on-chain will reject with
|
|
141
|
+
// AccountNotInitialized — we let that bubble up unchanged.
|
|
142
|
+
} catch (err) {
|
|
143
|
+
// Preflight is advisory; rethrow only the explicit coverage error.
|
|
144
|
+
if (err instanceof Error && err.message.startsWith("createEscrowV2: agent stake")) {
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
100
148
|
|
|
101
149
|
return this.methods
|
|
102
150
|
.createEscrowV2(
|
package/src/modules/escrow.ts
CHANGED
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
} from "../types";
|
|
34
34
|
import {
|
|
35
35
|
buildPriorityFeeIxs,
|
|
36
|
+
computeBatchSettleCu,
|
|
36
37
|
buildRpcOptions,
|
|
37
38
|
} from "../utils/priority-fee";
|
|
38
39
|
import type { SettleOptions } from "../utils/priority-fee";
|
|
@@ -305,12 +306,22 @@ export class EscrowModule extends BaseModule {
|
|
|
305
306
|
const rootArr = hashToArray(rootBytes);
|
|
306
307
|
const [receiptPda] = deriveSettlementReceipt(escrowPda, rootBytes);
|
|
307
308
|
|
|
308
|
-
|
|
309
|
-
|
|
309
|
+
// Auto-size CU to the batch length so callers don't have to think
|
|
310
|
+
// about it. The default Solana cap (200k) overflows past ~8
|
|
311
|
+
// settlements; we compute a tight ceiling and let the caller
|
|
312
|
+
// override via `opts.computeUnits` if they want.
|
|
313
|
+
// Setting the CU limit is FREE — it doesn't add lamports, only
|
|
314
|
+
// caps the maximum the runtime is allowed to charge.
|
|
315
|
+
const effectiveOpts: SettleOptions = {
|
|
316
|
+
...opts,
|
|
317
|
+
computeUnits: opts?.computeUnits ?? computeBatchSettleCu(settlements.length),
|
|
318
|
+
};
|
|
319
|
+
const preIxs = buildPriorityFeeIxs(effectiveOpts);
|
|
320
|
+
const rpcOpts = buildRpcOptions(effectiveOpts);
|
|
310
321
|
|
|
311
322
|
let builder = this.methods
|
|
312
323
|
.settleBatch(settlements, rootArr)
|
|
313
|
-
.
|
|
324
|
+
.accountsPartial({
|
|
314
325
|
wallet: this.walletPubkey,
|
|
315
326
|
agent: agentPda,
|
|
316
327
|
agentStats: statsPda,
|
package/src/modules/receipt.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
derivePendingSettlement as derivePendingPda,
|
|
26
26
|
deriveDispute as deriveDisputePda,
|
|
27
27
|
deriveReceiptBatch as deriveReceiptPda,
|
|
28
|
+
deriveStake,
|
|
28
29
|
} from "../pda";
|
|
29
30
|
import type { ReceiptBatchData } from "../types";
|
|
30
31
|
|
|
@@ -172,6 +173,9 @@ export class ReceiptModule extends BaseModule {
|
|
|
172
173
|
const [pendingPda] = derivePendingPda(escrowPda, this.toNum(settlementIndex));
|
|
173
174
|
const [disputePda] = deriveDisputePda(pendingPda);
|
|
174
175
|
const [statsPda] = deriveAgentStats(agentPda);
|
|
176
|
+
// v0.11 H-3: AgentStake is now a typed required account so the slash on
|
|
177
|
+
// DepositorWins is guaranteed instead of silently skipped.
|
|
178
|
+
const [stakePda] = deriveStake(agentPda);
|
|
175
179
|
|
|
176
180
|
return this.methods
|
|
177
181
|
.autoResolveDispute()
|
|
@@ -183,6 +187,7 @@ export class ReceiptModule extends BaseModule {
|
|
|
183
187
|
pendingSettlement: pendingPda,
|
|
184
188
|
dispute: disputePda,
|
|
185
189
|
agentStats: statsPda,
|
|
190
|
+
agentStake: stakePda,
|
|
186
191
|
})
|
|
187
192
|
.rpc();
|
|
188
193
|
}
|
package/src/modules/staking.ts
CHANGED
|
@@ -17,6 +17,10 @@ import { BN } from "@coral-xyz/anchor";
|
|
|
17
17
|
import { BaseModule } from "./base";
|
|
18
18
|
import { deriveAgent, deriveStake } from "../pda";
|
|
19
19
|
import type { AgentStakeData } from "../types";
|
|
20
|
+
import {
|
|
21
|
+
MIN_AGENT_STAKE_LAMPORTS,
|
|
22
|
+
computeRequiredStakeLamports,
|
|
23
|
+
} from "../constants/payments";
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* @name StakingModule
|
|
@@ -119,4 +123,35 @@ export class StakingModule extends BaseModule {
|
|
|
119
123
|
async fetchByPda(stakePda: PublicKey): Promise<AgentStakeData> {
|
|
120
124
|
return this.fetchAccount<AgentStakeData>("agentStake", stakePda);
|
|
121
125
|
}
|
|
126
|
+
|
|
127
|
+
// ── v0.11 helpers ────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Compute the maximum amount that can be requested via `requestUnstake`
|
|
131
|
+
* without breaching the on-chain {@link MIN_AGENT_STAKE_LAMPORTS} floor.
|
|
132
|
+
*
|
|
133
|
+
* Returns 0 if the agent is already at (or below) the floor.
|
|
134
|
+
*
|
|
135
|
+
* @since v0.11.0
|
|
136
|
+
*/
|
|
137
|
+
getMaxUnstakeLamports(stake: AgentStakeData): bigint {
|
|
138
|
+
const staked = BigInt(stake.stakedAmount.toString());
|
|
139
|
+
if (staked <= MIN_AGENT_STAKE_LAMPORTS) return 0n;
|
|
140
|
+
return staked - MIN_AGENT_STAKE_LAMPORTS;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns the lamport delta the agent must `deposit` to satisfy the
|
|
145
|
+
* per-escrow stake-coverage requirement for `escrowLamports`. 0 if already
|
|
146
|
+
* sufficient. Useful for a UI "top up to open this escrow" button.
|
|
147
|
+
*
|
|
148
|
+
* Mirrors the on-chain check in `create_escrow_v2` (v0.11 H-1).
|
|
149
|
+
*
|
|
150
|
+
* @since v0.11.0
|
|
151
|
+
*/
|
|
152
|
+
getRequiredTopUp(stake: AgentStakeData, escrowLamports: bigint): bigint {
|
|
153
|
+
const required = computeRequiredStakeLamports(escrowLamports);
|
|
154
|
+
const have = BigInt(stake.stakedAmount.toString());
|
|
155
|
+
return have >= required ? 0n : required - have;
|
|
156
|
+
}
|
|
122
157
|
}
|
package/src/registries/x402.ts
CHANGED
|
@@ -88,6 +88,7 @@ import type {
|
|
|
88
88
|
} from "../types";
|
|
89
89
|
import {
|
|
90
90
|
buildPriorityFeeIxs,
|
|
91
|
+
computeBatchSettleCu,
|
|
91
92
|
buildRpcOptions,
|
|
92
93
|
} from "../utils/priority-fee";
|
|
93
94
|
import type { SettleOptions } from "../utils/priority-fee";
|
|
@@ -856,13 +857,19 @@ export class X402Registry {
|
|
|
856
857
|
totalCalls,
|
|
857
858
|
);
|
|
858
859
|
|
|
859
|
-
//
|
|
860
|
-
|
|
861
|
-
|
|
860
|
+
// Auto-size CU to the batch length when the caller didn't pin one.
|
|
861
|
+
// Default Solana cap (200k) is tight past ~8 entries; a CU limit
|
|
862
|
+
// costs nothing extra (only caps the maximum charge).
|
|
863
|
+
const effectiveOpts: SettleOptions = {
|
|
864
|
+
...opts,
|
|
865
|
+
computeUnits: opts?.computeUnits ?? computeBatchSettleCu(settlements.length),
|
|
866
|
+
};
|
|
867
|
+
const preIxs = buildPriorityFeeIxs(effectiveOpts);
|
|
868
|
+
const rpcOpts = buildRpcOptions(effectiveOpts);
|
|
862
869
|
|
|
863
870
|
let builder = this.methods
|
|
864
871
|
.settleBatch(settlements)
|
|
865
|
-
.
|
|
872
|
+
.accountsPartial({
|
|
866
873
|
wallet: this.wallet,
|
|
867
874
|
agent: agentPda,
|
|
868
875
|
agentStats: statsPda,
|
package/src/utils/index.ts
CHANGED
|
@@ -59,6 +59,61 @@ export const DEFAULT_SETTLE_COMPUTE_UNITS = 100_000;
|
|
|
59
59
|
*/
|
|
60
60
|
export const DEFAULT_BATCH_SETTLE_COMPUTE_UNITS = 300_000;
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Per-settlement CU cost observed for `settle_batch` (sha256 of the
|
|
64
|
+
* service hash, dedup scan, volume-curve math, account writes).
|
|
65
|
+
*
|
|
66
|
+
* @since v0.11.0
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
const BATCH_SETTLE_CU_PER_ENTRY = 25_000;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Fixed CU overhead for a `settle_batch` transaction independent of
|
|
73
|
+
* the entry count (signature verify, account loads, transfer, event).
|
|
74
|
+
*
|
|
75
|
+
* @since v0.11.0
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
const BATCH_SETTLE_CU_BASE = 60_000;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Hard ceiling — Solana caps a single instruction at 1.4M CU. We
|
|
82
|
+
* stay below that so a transaction with extra preInstructions
|
|
83
|
+
* (priority-fee, ATA creation) still fits.
|
|
84
|
+
*
|
|
85
|
+
* @since v0.11.0
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
const BATCH_SETTLE_CU_MAX = 1_200_000;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @name computeBatchSettleCu
|
|
92
|
+
* @description Compute the CU limit needed by `settle_batch` for a
|
|
93
|
+
* given entry count. Returned value is safe to pass to
|
|
94
|
+
* `ComputeBudgetProgram.setComputeUnitLimit`.
|
|
95
|
+
*
|
|
96
|
+
* Formula: `60_000 + n * 25_000`, clamped to 1.2M.
|
|
97
|
+
*
|
|
98
|
+
* @param entryCount - Number of settlements in the batch (1..N).
|
|
99
|
+
* @returns CU limit suitable for `setComputeUnitLimit`.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* const cu = computeBatchSettleCu(20); // 560_000
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @category Utils
|
|
107
|
+
* @since v0.11.0
|
|
108
|
+
*/
|
|
109
|
+
export function computeBatchSettleCu(entryCount: number): number {
|
|
110
|
+
if (!Number.isFinite(entryCount) || entryCount <= 0) {
|
|
111
|
+
return DEFAULT_BATCH_SETTLE_COMPUTE_UNITS;
|
|
112
|
+
}
|
|
113
|
+
const raw = BATCH_SETTLE_CU_BASE + Math.ceil(entryCount) * BATCH_SETTLE_CU_PER_ENTRY;
|
|
114
|
+
return Math.min(raw, BATCH_SETTLE_CU_MAX);
|
|
115
|
+
}
|
|
116
|
+
|
|
62
117
|
// ═══════════════════════════════════════════════════════════════════
|
|
63
118
|
// Types
|
|
64
119
|
// ═══════════════════════════════════════════════════════════════════
|