@gvnrdao/dh-sdk 0.0.324 → 0.0.328

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.
@@ -329,7 +329,7 @@ var SEPOLIA_DEPLOYMENT = {
329
329
  CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
330
330
  CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
331
331
  AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
332
- AGENT_DELEGATION_REGISTRY_IMPL: "0x80C47350274513688e348D02506477A96B4afCCb",
332
+ AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
333
333
  DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
334
334
  }
335
335
  };
@@ -599,7 +599,7 @@ var MAINNET_CONTRACTS = {
599
599
  var LOCALHOST_DEPLOYMENT = {
600
600
  network: "localhost",
601
601
  chainId: 1337,
602
- timestamp: "2026-07-23T17:13:42.777Z",
602
+ timestamp: "2026-07-20T19:45:58.514Z",
603
603
  deployer: "",
604
604
  contracts: {
605
605
  MessageHashBuilder: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
@@ -619,30 +619,6 @@ var LOCALHOST_DEPLOYMENT = {
619
619
  PositionManager: "0x851356ae760d987E095750cCeb3bC6014560891C",
620
620
  OperationAuthorizationRegistry: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
621
621
  PKPValidation: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A"
622
- },
623
- latestEnv: {
624
- UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
625
- UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
626
- POSITION_MANAGER: "0x851356ae760d987E095750cCeb3bC6014560891C",
627
- PKP_VALIDATION_REGISTRY: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A",
628
- PKP_VALIDATION_CID_V1: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
629
- PKP_VALIDATION_CID_V3: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
630
- PKP_ETH_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
631
- OPERATION_AUTHORIZATION_REGISTRY: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
632
- UCD_MINT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
633
- UCD_MINT_VALIDATOR_VERSION: 1,
634
- BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
635
- BTC_WITHDRAWAL_VALIDATOR_VERSION: 3,
636
- UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
637
- UPDATE_BALANCE_VALIDATOR_VERSION: 1,
638
- PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
639
- PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
640
- EXTEND_POSITION_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
641
- EXTEND_POSITION_VALIDATOR_VERSION: 1,
642
- POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
643
- LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
644
- TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
645
- COMMUNITY_MANAGER_MODULE: ""
646
622
  }
647
623
  };
648
624
  var LOCALHOST_CONTRACTS = {
@@ -296,7 +296,7 @@ var SEPOLIA_DEPLOYMENT = {
296
296
  CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
297
297
  CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
298
298
  AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
299
- AGENT_DELEGATION_REGISTRY_IMPL: "0x80C47350274513688e348D02506477A96B4afCCb",
299
+ AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
300
300
  DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
301
301
  }
302
302
  };
@@ -566,7 +566,7 @@ var MAINNET_CONTRACTS = {
566
566
  var LOCALHOST_DEPLOYMENT = {
567
567
  network: "localhost",
568
568
  chainId: 1337,
569
- timestamp: "2026-07-23T17:13:42.777Z",
569
+ timestamp: "2026-07-20T19:45:58.514Z",
570
570
  deployer: "",
571
571
  contracts: {
572
572
  MessageHashBuilder: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
@@ -586,30 +586,6 @@ var LOCALHOST_DEPLOYMENT = {
586
586
  PositionManager: "0x851356ae760d987E095750cCeb3bC6014560891C",
587
587
  OperationAuthorizationRegistry: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
588
588
  PKPValidation: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A"
589
- },
590
- latestEnv: {
591
- UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
592
- UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
593
- POSITION_MANAGER: "0x851356ae760d987E095750cCeb3bC6014560891C",
594
- PKP_VALIDATION_REGISTRY: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A",
595
- PKP_VALIDATION_CID_V1: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
596
- PKP_VALIDATION_CID_V3: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
597
- PKP_ETH_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
598
- OPERATION_AUTHORIZATION_REGISTRY: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
599
- UCD_MINT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
600
- UCD_MINT_VALIDATOR_VERSION: 1,
601
- BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
602
- BTC_WITHDRAWAL_VALIDATOR_VERSION: 3,
603
- UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
604
- UPDATE_BALANCE_VALIDATOR_VERSION: 1,
605
- PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
606
- PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
607
- EXTEND_POSITION_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
608
- EXTEND_POSITION_VALIDATOR_VERSION: 1,
609
- POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
610
- LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
611
- TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
612
- COMMUNITY_MANAGER_MODULE: ""
613
589
  }
614
590
  };
615
591
  var LOCALHOST_CONTRACTS = {
package/dist/index.d.ts CHANGED
@@ -35,6 +35,7 @@ export type { BitcoinOperationsConfig, BitcoinNetwork, EnrichedBitcoinBalance, }
35
35
  export type { SupportedStablecoinData } from './graphs/diamond-hands';
36
36
  export { validateSDKConfig, validateServiceModeConfig, validateStandaloneModeConfig, isServiceModeConfig, isStandaloneModeConfig, } from './interfaces/chunks/config.i';
37
37
  export { assertSafeServiceEndpoint } from './utils/service-endpoint-policy';
38
+ export type { AuthorizationContext, AuthorizationProvider, } from './utils/authorization-provider.utils';
38
39
  export { buildLoginDomain, buildSignedLoginPayload, LOGIN_TYPES, LOGIN_TYPES_WITH_AUDIENCE, } from './utils/eip712-login';
39
40
  export type { DhServerLoginMessage, DhServerLoginPayload, } from './utils/eip712-login';
40
41
  export { DEFAULT_LIT_NETWORK, VALID_LIT_NETWORKS, SDK_DEFAULTS, } from './constants/chunks/sdk-config';
package/dist/index.js CHANGED
@@ -354,7 +354,7 @@ var init_deployment_addresses = __esm({
354
354
  CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
355
355
  CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
356
356
  AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
357
- AGENT_DELEGATION_REGISTRY_IMPL: "0x80C47350274513688e348D02506477A96B4afCCb",
357
+ AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
358
358
  DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
359
359
  }
360
360
  };
@@ -624,7 +624,7 @@ var init_deployment_addresses = __esm({
624
624
  LOCALHOST_DEPLOYMENT = {
625
625
  network: "localhost",
626
626
  chainId: 1337,
627
- timestamp: "2026-07-23T17:13:42.777Z",
627
+ timestamp: "2026-07-20T19:45:58.514Z",
628
628
  deployer: "",
629
629
  contracts: {
630
630
  MessageHashBuilder: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
@@ -644,30 +644,6 @@ var init_deployment_addresses = __esm({
644
644
  PositionManager: "0x851356ae760d987E095750cCeb3bC6014560891C",
645
645
  OperationAuthorizationRegistry: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
646
646
  PKPValidation: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A"
647
- },
648
- latestEnv: {
649
- UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
650
- UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
651
- POSITION_MANAGER: "0x851356ae760d987E095750cCeb3bC6014560891C",
652
- PKP_VALIDATION_REGISTRY: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A",
653
- PKP_VALIDATION_CID_V1: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
654
- PKP_VALIDATION_CID_V3: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
655
- PKP_ETH_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
656
- OPERATION_AUTHORIZATION_REGISTRY: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
657
- UCD_MINT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
658
- UCD_MINT_VALIDATOR_VERSION: 1,
659
- BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
660
- BTC_WITHDRAWAL_VALIDATOR_VERSION: 3,
661
- UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
662
- UPDATE_BALANCE_VALIDATOR_VERSION: 1,
663
- PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
664
- PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
665
- EXTEND_POSITION_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
666
- EXTEND_POSITION_VALIDATOR_VERSION: 1,
667
- POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
668
- LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
669
- TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
670
- COMMUNITY_MANAGER_MODULE: ""
671
647
  }
672
648
  };
673
649
  LOCALHOST_CONTRACTS = {
@@ -1387,7 +1363,7 @@ var require_pkg_src = __commonJS({
1387
1363
  description: "Production Btc Transaction Signer",
1388
1364
  version: "1.1.1",
1389
1365
  deployed: true,
1390
- deployedAt: 1786113907707,
1366
+ deployedAt: 1786465606156,
1391
1367
  size: 67999,
1392
1368
  hash: "83f3644c68819215e05ba8db3225571354a009458fc1437f606df6cb9142d3f9"
1393
1369
  },
@@ -1400,7 +1376,7 @@ var require_pkg_src = __commonJS({
1400
1376
  description: "Production Ucd Mint Validator",
1401
1377
  version: "1.2.1",
1402
1378
  deployed: true,
1403
- deployedAt: 1786113908489,
1379
+ deployedAt: 1786465627201,
1404
1380
  size: 82739,
1405
1381
  hash: "2bdd9aebdaad58a43a4731d5b7284f2531b7a9caaf8caf5719d891c4ed33cb2e",
1406
1382
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1418,7 +1394,7 @@ var require_pkg_src = __commonJS({
1418
1394
  description: "Production Process Payment Validator",
1419
1395
  version: "1.2.1",
1420
1396
  deployed: true,
1421
- deployedAt: 1786113909138,
1397
+ deployedAt: 1786465654796,
1422
1398
  size: 78736,
1423
1399
  hash: "17191ecc9c009e0fa5ab52c876330beb2a9a75d30cccb92e7c0c04f169df088b",
1424
1400
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1436,7 +1412,7 @@ var require_pkg_src = __commonJS({
1436
1412
  description: "Production Extend Position Validator",
1437
1413
  version: "1.2.1",
1438
1414
  deployed: true,
1439
- deployedAt: 1786113909872,
1415
+ deployedAt: 1786465681874,
1440
1416
  size: 76515,
1441
1417
  hash: "1d4e085335af80f194a663a577876902c83015177e95906a0b461fa93bd5da08",
1442
1418
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
@@ -1446,21 +1422,17 @@ var require_pkg_src = __commonJS({
1446
1422
  }
1447
1423
  },
1448
1424
  btcWithdrawal: {
1449
- cid: "QmZuR3qSBajutXfRd91ffpyFrRMgmaMh7fDEHRiQQF8Ljp",
1425
+ cid: "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh",
1450
1426
  authorizedCidHex: cidToHex(
1451
- "QmZuR3qSBajutXfRd91ffpyFrRMgmaMh7fDEHRiQQF8Ljp"
1427
+ "QmRYVoTTDxk2McvBqxSm9M7YcaBGdTqjnZGPX4Y191DaZh"
1452
1428
  ),
1453
1429
  name: "Btc Withdrawal",
1454
1430
  description: "Production Btc Withdrawal",
1455
- // Monotonic per action, NOT a shared release train — the EIP-1271 rotation
1456
- // stamped its cohort 1.2.1, but this action was already at 1.2.3 from the vout
1457
- // canonicalization fix. Reusing the cohort stamp made a newer CID read as older
1458
- // than the one it replaced, which a rotation ceremony would treat as a rollback.
1459
- version: "1.2.4",
1431
+ version: "1.2.7",
1460
1432
  deployed: true,
1461
- deployedAt: 1786113910531,
1462
- size: 95313,
1463
- hash: "ce12f11e3b5469953bc919586e4f3b8b5d594224b58b799dd9a3b60e3749559c",
1433
+ deployedAt: 1786446046614,
1434
+ size: 97456,
1435
+ hash: "3cae8250861832f91ee3c573abeb50ff27b9acd34148176071cbfbabb359fc91",
1464
1436
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1465
1437
  pkp: {
1466
1438
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -1572,19 +1544,17 @@ var require_pkg_src = __commonJS({
1572
1544
  hash: "03ee5be239c91c735d2c95db89a0d1b77e602cfc18af8eb64b3281fddcd90a72"
1573
1545
  },
1574
1546
  agentModuleExecutor: {
1575
- // Bound to the isolated Sepolia agent group 7 ("DH-Agent-Sepolia"), which
1576
- // holds this action and no PKPs until an agent is minted into it. NOT yet
1577
- // bound on mainnet — the Base `DH-Agent-Mainnet` group is created at rollout.
1578
- cid: "QmVgjGXUuxoGf8XyddW8a7btaazT9yEotpKoBgb65oPvcF",
1547
+ cid: "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ",
1579
1548
  authorizedCidHex: cidToHex(
1580
- "QmVgjGXUuxoGf8XyddW8a7btaazT9yEotpKoBgb65oPvcF"
1549
+ "QmdhC18wF7PFGMQ8aThdPsEVSpuDewA27dFvbA3bG6kVDQ"
1581
1550
  ),
1582
1551
  name: "Agent Module Executor",
1583
- description: "Capability gate for multi-sig Safe agent delegation: binds the agent PKP to the AgentDelegationRegistry record before signing (authorize | execute modes)",
1584
- version: "1.0.0",
1552
+ description: "Production Agent Module Executor",
1553
+ version: "1.1.1",
1585
1554
  deployed: true,
1586
- size: 11785,
1587
- hash: "fa294e164273c2158f9ef11a0ccfd735c343c0e3759fcb4b37e0f8a5d1ab0d29"
1555
+ deployedAt: 1786446108348,
1556
+ size: 11655,
1557
+ hash: "d4e2149f843d6c2699fc61114d54b268ba4ed2c46ebdaee1145e0f101ec2a1ec"
1588
1558
  },
1589
1559
  staleSpendRecoveryValidator: {
1590
1560
  cid: "QmXQWT8V4wjuvH8BbC7xrkYxsVu5AKfvfWcS7jnYfrexYm",
@@ -1613,7 +1583,7 @@ var require_pkg_src = __commonJS({
1613
1583
  description: "Production Btc Utxo Invalidator",
1614
1584
  version: "1.0.0",
1615
1585
  deployed: true,
1616
- deployedAt: 1786113911948,
1586
+ deployedAt: 1786465704240,
1617
1587
  size: 62553,
1618
1588
  hash: "1dcea2b49e545c423195be22e072dc5e3039ed1c95a8490b23505956029f5b33"
1619
1589
  }
@@ -5522,8 +5492,14 @@ function getMainnetConfig() {
5522
5492
  agentModuleFactory: MAINNET_CONTRACTS.AgentModuleFactory || ""
5523
5493
  },
5524
5494
  subgraphs: {
5495
+ // KNOWN-WRONG placeholder (see GOAL-PLAN step 2 / dogfood F-CLI-4): this is a
5496
+ // SEPOLIA subgraph id in a mainnet (chainId 1) config, and this gateway host
5497
+ // needs an Authorization key the SDK does not (and must not) hold — so the
5498
+ // URL is doubly unusable. The `CCTPsd…` path segment is the subgraph's
5499
+ // PUBLIC ID, not a credential. The fix is a chain-correct SERVER-side proxy
5500
+ // (see mcp/docs/SUBGRAPH-PROXY-PLAN.md) — same rule as rpcUrls above:
5501
+ // never ship an API-keyed URL in a client config.
5525
5502
  diamondHandsUrl: "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/CCTPsdYqco2jChDLLBQTbdJWwoukVoMt1cXeR9ti6r9A"
5526
- // Published Sepolia subgraph on Arbitrum One
5527
5503
  },
5528
5504
  litNetwork: "chipotle",
5529
5505
  debug: false
@@ -6415,7 +6391,7 @@ async function generateMintAuthorization(positionId, amount, chainId, signerOrPr
6415
6391
  signature
6416
6392
  };
6417
6393
  }
6418
- async function generatePaymentAuthorization(positionId, amount, chainId, signer) {
6394
+ async function generatePaymentAuthorization(positionId, amount, chainId, signerOrPrecomputed) {
6419
6395
  if (typeof positionId !== "string") {
6420
6396
  throw new Error(`positionId must be a string, got ${typeof positionId}`);
6421
6397
  }
@@ -6425,6 +6401,18 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
6425
6401
  if (typeof chainId !== "number") {
6426
6402
  throw new Error(`chainId must be a number, got ${typeof chainId}`);
6427
6403
  }
6404
+ if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
6405
+ const { timestamp: timestamp2, signature: signature2 } = signerOrPrecomputed;
6406
+ return {
6407
+ positionId,
6408
+ timestamp: timestamp2,
6409
+ chainId,
6410
+ amount: amount.toString(),
6411
+ action: "make-payment",
6412
+ signature: signature2
6413
+ };
6414
+ }
6415
+ const signer = signerOrPrecomputed;
6428
6416
  const timestamp = await calculateNextQuantumTimestamp();
6429
6417
  if (typeof timestamp !== "number") {
6430
6418
  throw new Error(`timestamp must be a number, got ${typeof timestamp}`);
@@ -6666,6 +6654,26 @@ async function generateExtendAuthorization(positionId, newTerm, chainId, signerO
6666
6654
  };
6667
6655
  }
6668
6656
 
6657
+ // src/utils/authorization-provider.utils.ts
6658
+ async function resolveAuthorizationInput(provider, signer, ctx) {
6659
+ if (!provider)
6660
+ return signer;
6661
+ const result = await provider(ctx);
6662
+ if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
6663
+ throw new Error(
6664
+ "authorizationProvider returned no signature \u2014 refusing to fall back to the connected signer, which would prompt for the owner quorum this provider exists to avoid"
6665
+ );
6666
+ }
6667
+ if (!Number.isInteger(result.timestamp)) {
6668
+ throw new Error(
6669
+ `authorizationProvider returned a non-integer timestamp (${String(
6670
+ result.timestamp
6671
+ )}) \u2014 the protocol call must carry the same value the envelope was signed over`
6672
+ );
6673
+ }
6674
+ return { timestamp: result.timestamp, signature: result.signature };
6675
+ }
6676
+
6669
6677
  // src/utils/eip712-login.ts
6670
6678
  var import_ethers4 = require("ethers");
6671
6679
  function buildLoginDomain(chainId) {
@@ -20077,11 +20085,20 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
20077
20085
  {}
20078
20086
  );
20079
20087
  }
20088
+ const mintAuthInput = await resolveAuthorizationInput(
20089
+ request.authorizationProvider,
20090
+ signer2,
20091
+ {
20092
+ positionId: request.positionId,
20093
+ timestamp: calculateNextQuantumTimestamp(),
20094
+ amount: requestAmountWei.toString()
20095
+ }
20096
+ );
20080
20097
  const auth = await generateMintAuthorization(
20081
20098
  request.positionId,
20082
20099
  BigInt(requestAmountWei.toString()),
20083
20100
  chainId,
20084
- signer2
20101
+ mintAuthInput
20085
20102
  );
20086
20103
  if (this.config.debug) {
20087
20104
  log.info(` Authorization generated (attempt ${attempt})`, {});
@@ -21672,7 +21689,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
21672
21689
  * @param _selectedTerm - Extension term in months
21673
21690
  * @returns Transaction receipt
21674
21691
  */
21675
- async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl) {
21692
+ async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl, _authorizationProvider) {
21676
21693
  this.ensureInitialized();
21677
21694
  if (typeof _positionId !== "string") {
21678
21695
  throw new Error(`positionId must be a string, got ${typeof _positionId}`);
@@ -21766,11 +21783,23 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
21766
21783
  }
21767
21784
  }
21768
21785
  const signer = this.getSignerOrThrow();
21786
+ const extendAuthInput = await resolveAuthorizationInput(
21787
+ _authorizationProvider,
21788
+ signer,
21789
+ {
21790
+ positionId: _positionId,
21791
+ timestamp: calculateNextQuantumTimestamp(),
21792
+ // The extend envelope binds the TERM, not an amount. Carried as "0" so
21793
+ // the context shape stays uniform across the four operations.
21794
+ amount: "0",
21795
+ selectedTerm: _selectedTerm
21796
+ }
21797
+ );
21769
21798
  const auth = await generateExtendAuthorization(
21770
21799
  _positionId,
21771
21800
  _selectedTerm,
21772
21801
  chainId,
21773
- signer
21802
+ extendAuthInput
21774
21803
  );
21775
21804
  if (this.config.debug) {
21776
21805
  log.info(" Extend authorization generated", {
@@ -22026,7 +22055,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
22026
22055
  positionId,
22027
22056
  selectedTerm,
22028
22057
  request.rpcUrl,
22029
- request.customBitcoinRpcUrl
22058
+ request.customBitcoinRpcUrl,
22059
+ request.authorizationProvider
22030
22060
  );
22031
22061
  let newExpiryAt;
22032
22062
  try {
@@ -22554,11 +22584,20 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
22554
22584
  }
22555
22585
  let auth;
22556
22586
  try {
22587
+ const paymentAuthInput = await resolveAuthorizationInput(
22588
+ request.authorizationProvider,
22589
+ signer,
22590
+ {
22591
+ positionId: request.positionId,
22592
+ timestamp: calculateNextQuantumTimestamp(),
22593
+ amount: paymentAmountWei.toString()
22594
+ }
22595
+ );
22557
22596
  auth = await generatePaymentAuthorization(
22558
22597
  request.positionId,
22559
22598
  paymentAmountWei,
22560
22599
  chainId,
22561
- signer
22600
+ paymentAuthInput
22562
22601
  );
22563
22602
  } catch (authError) {
22564
22603
  if (authError.message && authError.message.includes("BigNumber")) {
@@ -23070,7 +23109,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
23070
23109
  * @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
23071
23110
  * @returns Withdrawal result with transaction details
23072
23111
  */
23073
- async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount) {
23112
+ async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount, options) {
23074
23113
  this.ensureInitialized();
23075
23114
  try {
23076
23115
  if (this.config.debug) {
@@ -23285,11 +23324,21 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
23285
23324
  {}
23286
23325
  );
23287
23326
  }
23327
+ const withdrawAuthInput = await resolveAuthorizationInput(
23328
+ options?.authorizationProvider,
23329
+ signer,
23330
+ {
23331
+ positionId,
23332
+ timestamp: calculateNextQuantumTimestamp(),
23333
+ amount: BigInt(withdrawalAmount).toString(),
23334
+ destinationAddress: withdrawalAddress
23335
+ }
23336
+ );
23288
23337
  const auth = await generateWithdrawAuthorization(
23289
23338
  positionId,
23290
23339
  BigInt(withdrawalAmount),
23291
23340
  chainId,
23292
- signer,
23341
+ withdrawAuthInput,
23293
23342
  withdrawalAddress
23294
23343
  // Pass destination address for message hash
23295
23344
  );
@@ -24363,6 +24412,11 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24363
24412
  * (`MAX_ATTESTATION_AGE = 1 hour`) and replay-protects via
24364
24413
  * `authorizedAt` binding.
24365
24414
  *
24415
+ * WHO PAYS: in **service mode** lit-ops-server performs BOTH steps and its
24416
+ * relayer funds the transaction — the borrower is never prompted, because the
24417
+ * Bitcoin withdrawal this cleans up after has already settled. In **direct
24418
+ * mode** (CLI / tests / hardhat) the SDK's own signer submits step 2.
24419
+ *
24366
24420
  * `invalidatorTxid` is either:
24367
24421
  * - the borrower's own authorized broadcast (classified "consumed-as-authorized"
24368
24422
  * by the LIT validator), once it has ≥6 confirmations on the BTC
@@ -24375,7 +24429,6 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24375
24429
  async recoverStaleSpend(params) {
24376
24430
  this.ensureInitialized();
24377
24431
  try {
24378
- const signer = this.getSignerOrThrow();
24379
24432
  const contractAddresses = this.getContractAddressesOrThrow();
24380
24433
  const btcSpendAuthorizerAddress = contractAddresses.btcSpendAuthorizer;
24381
24434
  if (!btcSpendAuthorizerAddress) {
@@ -24421,6 +24474,28 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24421
24474
  success: false,
24422
24475
  error: json.error ?? "stale-spend recovery request failed"
24423
24476
  };
24477
+ if (!attRes.success || !attRes.attestation) {
24478
+ return {
24479
+ success: false,
24480
+ failedStep: "attestation",
24481
+ error: attRes.error ?? attRes.reason ?? `LIT recovery attestation rejected${attRes.failedStep ? ` at step ${attRes.failedStep}` : ""}`
24482
+ };
24483
+ }
24484
+ if (!attRes.transactionHash && !attRes.alreadyCleared) {
24485
+ return {
24486
+ success: false,
24487
+ failedStep: "submit",
24488
+ error: "lit-ops-server returned a stale-spend attestation but did not submit it. The server is on a build without the recovery relayer, or its STALE_SPEND_RELAYER_PRIVATE_KEY is unset."
24489
+ };
24490
+ }
24491
+ return {
24492
+ success: true,
24493
+ ...attRes.transactionHash && {
24494
+ transactionHash: attRes.transactionHash
24495
+ },
24496
+ ...attRes.classification && { classification: attRes.classification },
24497
+ attestation: attRes.attestation
24498
+ };
24424
24499
  } else {
24425
24500
  const rpcUrl = params.rpcUrl ?? this.config.ethRpcUrl;
24426
24501
  if (!rpcUrl) {
@@ -24430,6 +24505,13 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24430
24505
  error: "ethRpcUrl required for recoverStaleSpend \u2014 set DiamondHandsSDKConfig.ethRpcUrl or pass rpcUrl"
24431
24506
  };
24432
24507
  }
24508
+ if (!this.config.contractSigner) {
24509
+ return {
24510
+ success: false,
24511
+ failedStep: "config",
24512
+ error: "Contract signer not configured \u2014 recoverStaleSpend submits its own recovery transaction in direct mode. Set DiamondHandsSDKConfig.contractSigner, or use service mode, where the server relays and pays for it."
24513
+ };
24514
+ }
24433
24515
  const sdkBitcoinProviderUrl = this.config.bitcoinProviders?.[0]?.url;
24434
24516
  attRes = await this.litOps.requestStaleSpendRecoveryAttestation({
24435
24517
  chainId,
@@ -24470,7 +24552,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
24470
24552
  [
24471
24553
  "function cancelStaleSpendWithProof(bytes32 positionId, bytes32 utxoKey, uint256 authorizedAt, string calldata invalidatorTxid, uint256 attestationTimestamp, bytes calldata litSignature) external"
24472
24554
  ],
24473
- signer
24555
+ this.getSignerOrThrow()
24474
24556
  );
24475
24557
  const tx = await btcSpendAuthorizer["cancelStaleSpendWithProof"](
24476
24558
  attRes.attestation.positionId,
@@ -25278,10 +25360,22 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25278
25360
  "getLoanGrant",
25279
25361
  data
25280
25362
  );
25363
+ const raw = (0, import_ethers17.getBytes)(data);
25364
+ const withdrawScopeSupported = raw.length >= 128;
25365
+ const minWithdrawRatioBps = withdrawScopeSupported ? Number(
25366
+ import_ethers17.AbiCoder.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
25367
+ ) : 0;
25281
25368
  return {
25282
25369
  borrower,
25283
25370
  scopeBits: Number(scopeBits),
25284
- minCollateralRatioBps: Number(minCollateralRatioBps)
25371
+ minCollateralRatioBps: Number(minCollateralRatioBps),
25372
+ minWithdrawRatioBps,
25373
+ /**
25374
+ * True when the deployed registry is v2.1.0+ and therefore honours `SCOPE_WITHDRAW`. The
25375
+ * frontend gates its Withdrawal control on this so the control is absent — not disabled,
25376
+ * not "coming soon" — on a chain whose registry cannot support it.
25377
+ */
25378
+ withdrawScopeSupported
25285
25379
  };
25286
25380
  }
25287
25381
  /**
@@ -25323,10 +25417,14 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25323
25417
  const mintEnabled = hasGrant && (scopes & 4) !== 0;
25324
25418
  const floor = grant.minCollateralRatioBps;
25325
25419
  const agent = user ? await registry.agentOf(user) : null;
25420
+ const withdrawEnabled = hasGrant && grant.withdrawScopeSupported && (scopes & 8) !== 0;
25326
25421
  return {
25327
25422
  renewEnabled: hasGrant && (scopes & 1) !== 0,
25328
25423
  repayEnabled: hasGrant && (scopes & 2) !== 0,
25329
25424
  mintEnabled,
25425
+ withdrawEnabled,
25426
+ withdrawScopeSupported: grant.withdrawScopeSupported,
25427
+ minWithdrawRatioBps: withdrawEnabled ? grant.minWithdrawRatioBps : 0,
25330
25428
  minCollateralRatioBps: mintEnabled ? floor : 0,
25331
25429
  effectiveMintFloorBps: mintEnabled ? Math.max(floor, protocolMin) : 0,
25332
25430
  protocolMinFloorBps: protocolMin,
@@ -25512,8 +25610,83 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25512
25610
  const receipt = await tx.wait();
25513
25611
  return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
25514
25612
  }
25515
- /** Pre-flight the registry's `FloorBelowProtocolMin` guard with a message a user can act on. */
25516
- async assertMintFloorAtOrAboveProtocolMin(floorBps) {
25613
+ /**
25614
+ * Grant the agent the WITHDRAW scope for a position (registry v2.1.0+). Borrower-signed.
25615
+ *
25616
+ * CONTRACT WALLETS ONLY, and this is enforced here rather than on-chain. The withdrawal
25617
+ * validator's only non-borrower arm is `checkSafeAgentWithdrawAuthorization`, which requires a
25618
+ * factory-provenanced `AgentModule` whose `safe()` is the borrower — something an EOA cannot
25619
+ * have. The registry deliberately does NOT check wallet type ("Callable by any borrower (this
25620
+ * function does not itself require a Safe)"), so an EOA can record a grant that no code path
25621
+ * will ever satisfy. Refusing here keeps the supported path from writing a dead record.
25622
+ *
25623
+ * That refusal is ergonomics, NOT enforcement — `enableAutoWithdraw` is `external` and reachable
25624
+ * from any wallet. The real reason delegated withdrawal is closed to EOAs is that they can sign
25625
+ * inside the ~44s window themselves, so delegating buys them nothing and only adds risk.
25626
+ *
25627
+ * @param minWithdrawRatioBps Post-withdrawal collateral-ratio floor for AGENT withdrawals.
25628
+ * Clamped by the same governance minimum as the mint floor. **Inert at zero debt** — it
25629
+ * is a ratio, and the post-withdrawal ratio is infinite for any amount once debt is 0.
25630
+ * The operative bound there is the quorum-gated destination allowlist. Do not surface
25631
+ * this to users as a cap on how much an agent may withdraw.
25632
+ * There is no in-place raise: changing it means disable-then-re-enable, deliberately —
25633
+ * on the one scope that moves custodied BTC, incident response can only disable outright.
25634
+ */
25635
+ async enableAutoWithdraw(positionId, minWithdrawRatioBps, options) {
25636
+ const pid = this.toBytes32(positionId);
25637
+ await this.assertBorrowerIsContractWallet(pid);
25638
+ await this.assertMintFloorAtOrAboveProtocolMin(minWithdrawRatioBps, "withdraw");
25639
+ const { registry, agentAddress } = await this.prepareAgentDelegation(pid, options);
25640
+ const tx = await registry.enableAutoWithdraw(pid, minWithdrawRatioBps);
25641
+ const receipt = await tx.wait();
25642
+ return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0, agentAddress };
25643
+ }
25644
+ /**
25645
+ * Revoke the WITHDRAW scope for a position (also zeroes its withdraw floor). Borrower-signed.
25646
+ *
25647
+ * No wallet-type check: revoking is the safe direction, and an EOA that recorded a grant before
25648
+ * this guard existed must be able to clear it.
25649
+ */
25650
+ async disableAutoWithdraw(positionId) {
25651
+ const addr = this.agentDelegationRegistryOrThrow();
25652
+ const signer = this.getSignerOrThrow();
25653
+ const registry = AgentDelegationRegistry__factory.connect(addr, signer);
25654
+ const pid = this.toBytes32(positionId);
25655
+ const tx = await registry.disableAutoWithdraw(pid);
25656
+ const receipt = await tx.wait();
25657
+ await this.clearGate1IfNoScopesRemain(pid);
25658
+ return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
25659
+ }
25660
+ /**
25661
+ * Layer 2 of the withdrawal-delegation gating: refuse to write a grant that could never be
25662
+ * satisfied. See `enableAutoWithdraw` for why this lives here and not in the registry.
25663
+ */
25664
+ async assertBorrowerIsContractWallet(pid) {
25665
+ const details = await this.getPositionDetailsView(pid);
25666
+ const borrower = details?.borrower;
25667
+ if (!borrower) {
25668
+ throw new SDKError({
25669
+ message: `Could not resolve the borrower for position ${pid} \u2014 refusing to write a delegation grant against an unverified position`,
25670
+ category: "VALIDATION" /* VALIDATION */,
25671
+ severity: "HIGH" /* HIGH */
25672
+ });
25673
+ }
25674
+ const code = await this.getProviderOrThrow().getCode(borrower);
25675
+ if (!code || code === "0x") {
25676
+ throw new SDKError({
25677
+ message: `Withdrawal delegation is only available to contract wallets. Borrower ${borrower} is an EOA, and the withdrawal validator has no delegate arm for one \u2014 an EOA can sign inside the withdrawal quantum window itself, so the grant would be recorded on-chain and never honoured.`,
25678
+ category: "VALIDATION" /* VALIDATION */,
25679
+ severity: "MEDIUM" /* MEDIUM */
25680
+ });
25681
+ }
25682
+ }
25683
+ /**
25684
+ * Pre-flight the registry's `FloorBelowProtocolMin` guard with a message a user can act on.
25685
+ *
25686
+ * `agentMintFloorMinBps` is the governance floor-of-floors for BOTH the mint and withdraw
25687
+ * grants — one lever, one invariant — so `scope` only shapes the message.
25688
+ */
25689
+ async assertMintFloorAtOrAboveProtocolMin(floorBps, scope = "mint") {
25517
25690
  if (!Number.isInteger(floorBps) || floorBps <= 0) {
25518
25691
  throw new SDKError({
25519
25692
  message: `Invalid collateral floor: ${floorBps} bps \u2014 must be a positive integer`,
@@ -25524,7 +25697,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
25524
25697
  const protocolMin = await this.getAgentMintFloorMinBps();
25525
25698
  if (protocolMin === 0) {
25526
25699
  throw new SDKError({
25527
- message: "Agent minting is not configured on this network (agentMintFloorMinBps is 0) \u2014 the registry would reject every mint grant",
25700
+ message: `Agent ${scope === "mint" ? "minting" : "withdrawal"} is not configured on this network (agentMintFloorMinBps is 0) \u2014 the registry would reject every ${scope} grant`,
25528
25701
  category: "CONFIGURATION" /* CONFIGURATION */,
25529
25702
  severity: "HIGH" /* HIGH */
25530
25703
  });