@gvnrdao/dh-sdk 0.0.324 → 0.0.327
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/browser/dist/browser.js +1 -1
- package/dist/deployments.js +2 -26
- package/dist/deployments.mjs +2 -26
- package/dist/index.d.ts +1 -0
- package/dist/index.js +213 -41
- package/dist/index.mjs +213 -41
- package/dist/interfaces/chunks/loan-operations.i.d.ts +37 -0
- package/dist/modules/diamond-hands-sdk.d.ts +75 -2
- package/dist/safe-delegation.js +2 -26
- package/dist/safe-delegation.mjs +2 -26
- package/dist/utils/authorization-provider.utils.d.ts +65 -0
- package/dist/utils/mint-authorization.utils.d.ts +10 -16
- package/package.json +2 -2
- package/browser/dist/397.browser.js +0 -2
- package/browser/dist/397.browser.js.LICENSE.txt +0 -1
- package/browser/dist/833.browser.js +0 -2
- package/browser/dist/833.browser.js.LICENSE.txt +0 -1
- package/browser/dist/index.d.ts +0 -8
- package/browser/dist/index.d.ts.map +0 -1
- package/browser/dist/index.js +0 -25
package/dist/deployments.js
CHANGED
|
@@ -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: "
|
|
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-
|
|
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 = {
|
package/dist/deployments.mjs
CHANGED
|
@@ -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: "
|
|
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-
|
|
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: "
|
|
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-
|
|
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 = {
|
|
@@ -5522,8 +5498,14 @@ function getMainnetConfig() {
|
|
|
5522
5498
|
agentModuleFactory: MAINNET_CONTRACTS.AgentModuleFactory || ""
|
|
5523
5499
|
},
|
|
5524
5500
|
subgraphs: {
|
|
5501
|
+
// KNOWN-WRONG placeholder (see GOAL-PLAN step 2 / dogfood F-CLI-4): this is a
|
|
5502
|
+
// SEPOLIA subgraph id in a mainnet (chainId 1) config, and this gateway host
|
|
5503
|
+
// needs an Authorization key the SDK does not (and must not) hold — so the
|
|
5504
|
+
// URL is doubly unusable. The `CCTPsd…` path segment is the subgraph's
|
|
5505
|
+
// PUBLIC ID, not a credential. The fix is a chain-correct SERVER-side proxy
|
|
5506
|
+
// (see mcp/docs/SUBGRAPH-PROXY-PLAN.md) — same rule as rpcUrls above:
|
|
5507
|
+
// never ship an API-keyed URL in a client config.
|
|
5525
5508
|
diamondHandsUrl: "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/CCTPsdYqco2jChDLLBQTbdJWwoukVoMt1cXeR9ti6r9A"
|
|
5526
|
-
// Published Sepolia subgraph on Arbitrum One
|
|
5527
5509
|
},
|
|
5528
5510
|
litNetwork: "chipotle",
|
|
5529
5511
|
debug: false
|
|
@@ -6415,7 +6397,7 @@ async function generateMintAuthorization(positionId, amount, chainId, signerOrPr
|
|
|
6415
6397
|
signature
|
|
6416
6398
|
};
|
|
6417
6399
|
}
|
|
6418
|
-
async function generatePaymentAuthorization(positionId, amount, chainId,
|
|
6400
|
+
async function generatePaymentAuthorization(positionId, amount, chainId, signerOrPrecomputed) {
|
|
6419
6401
|
if (typeof positionId !== "string") {
|
|
6420
6402
|
throw new Error(`positionId must be a string, got ${typeof positionId}`);
|
|
6421
6403
|
}
|
|
@@ -6425,6 +6407,18 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
|
|
|
6425
6407
|
if (typeof chainId !== "number") {
|
|
6426
6408
|
throw new Error(`chainId must be a number, got ${typeof chainId}`);
|
|
6427
6409
|
}
|
|
6410
|
+
if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
|
|
6411
|
+
const { timestamp: timestamp2, signature: signature2 } = signerOrPrecomputed;
|
|
6412
|
+
return {
|
|
6413
|
+
positionId,
|
|
6414
|
+
timestamp: timestamp2,
|
|
6415
|
+
chainId,
|
|
6416
|
+
amount: amount.toString(),
|
|
6417
|
+
action: "make-payment",
|
|
6418
|
+
signature: signature2
|
|
6419
|
+
};
|
|
6420
|
+
}
|
|
6421
|
+
const signer = signerOrPrecomputed;
|
|
6428
6422
|
const timestamp = await calculateNextQuantumTimestamp();
|
|
6429
6423
|
if (typeof timestamp !== "number") {
|
|
6430
6424
|
throw new Error(`timestamp must be a number, got ${typeof timestamp}`);
|
|
@@ -6666,6 +6660,26 @@ async function generateExtendAuthorization(positionId, newTerm, chainId, signerO
|
|
|
6666
6660
|
};
|
|
6667
6661
|
}
|
|
6668
6662
|
|
|
6663
|
+
// src/utils/authorization-provider.utils.ts
|
|
6664
|
+
async function resolveAuthorizationInput(provider, signer, ctx) {
|
|
6665
|
+
if (!provider)
|
|
6666
|
+
return signer;
|
|
6667
|
+
const result = await provider(ctx);
|
|
6668
|
+
if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
|
|
6669
|
+
throw new Error(
|
|
6670
|
+
"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"
|
|
6671
|
+
);
|
|
6672
|
+
}
|
|
6673
|
+
if (!Number.isInteger(result.timestamp)) {
|
|
6674
|
+
throw new Error(
|
|
6675
|
+
`authorizationProvider returned a non-integer timestamp (${String(
|
|
6676
|
+
result.timestamp
|
|
6677
|
+
)}) \u2014 the protocol call must carry the same value the envelope was signed over`
|
|
6678
|
+
);
|
|
6679
|
+
}
|
|
6680
|
+
return { timestamp: result.timestamp, signature: result.signature };
|
|
6681
|
+
}
|
|
6682
|
+
|
|
6669
6683
|
// src/utils/eip712-login.ts
|
|
6670
6684
|
var import_ethers4 = require("ethers");
|
|
6671
6685
|
function buildLoginDomain(chainId) {
|
|
@@ -20077,11 +20091,20 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20077
20091
|
{}
|
|
20078
20092
|
);
|
|
20079
20093
|
}
|
|
20094
|
+
const mintAuthInput = await resolveAuthorizationInput(
|
|
20095
|
+
request.authorizationProvider,
|
|
20096
|
+
signer2,
|
|
20097
|
+
{
|
|
20098
|
+
positionId: request.positionId,
|
|
20099
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
20100
|
+
amount: requestAmountWei.toString()
|
|
20101
|
+
}
|
|
20102
|
+
);
|
|
20080
20103
|
const auth = await generateMintAuthorization(
|
|
20081
20104
|
request.positionId,
|
|
20082
20105
|
BigInt(requestAmountWei.toString()),
|
|
20083
20106
|
chainId,
|
|
20084
|
-
|
|
20107
|
+
mintAuthInput
|
|
20085
20108
|
);
|
|
20086
20109
|
if (this.config.debug) {
|
|
20087
20110
|
log.info(` Authorization generated (attempt ${attempt})`, {});
|
|
@@ -21672,7 +21695,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
21672
21695
|
* @param _selectedTerm - Extension term in months
|
|
21673
21696
|
* @returns Transaction receipt
|
|
21674
21697
|
*/
|
|
21675
|
-
async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl) {
|
|
21698
|
+
async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl, _authorizationProvider) {
|
|
21676
21699
|
this.ensureInitialized();
|
|
21677
21700
|
if (typeof _positionId !== "string") {
|
|
21678
21701
|
throw new Error(`positionId must be a string, got ${typeof _positionId}`);
|
|
@@ -21766,11 +21789,23 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
21766
21789
|
}
|
|
21767
21790
|
}
|
|
21768
21791
|
const signer = this.getSignerOrThrow();
|
|
21792
|
+
const extendAuthInput = await resolveAuthorizationInput(
|
|
21793
|
+
_authorizationProvider,
|
|
21794
|
+
signer,
|
|
21795
|
+
{
|
|
21796
|
+
positionId: _positionId,
|
|
21797
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
21798
|
+
// The extend envelope binds the TERM, not an amount. Carried as "0" so
|
|
21799
|
+
// the context shape stays uniform across the four operations.
|
|
21800
|
+
amount: "0",
|
|
21801
|
+
selectedTerm: _selectedTerm
|
|
21802
|
+
}
|
|
21803
|
+
);
|
|
21769
21804
|
const auth = await generateExtendAuthorization(
|
|
21770
21805
|
_positionId,
|
|
21771
21806
|
_selectedTerm,
|
|
21772
21807
|
chainId,
|
|
21773
|
-
|
|
21808
|
+
extendAuthInput
|
|
21774
21809
|
);
|
|
21775
21810
|
if (this.config.debug) {
|
|
21776
21811
|
log.info(" Extend authorization generated", {
|
|
@@ -22026,7 +22061,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
22026
22061
|
positionId,
|
|
22027
22062
|
selectedTerm,
|
|
22028
22063
|
request.rpcUrl,
|
|
22029
|
-
request.customBitcoinRpcUrl
|
|
22064
|
+
request.customBitcoinRpcUrl,
|
|
22065
|
+
request.authorizationProvider
|
|
22030
22066
|
);
|
|
22031
22067
|
let newExpiryAt;
|
|
22032
22068
|
try {
|
|
@@ -22554,11 +22590,20 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
22554
22590
|
}
|
|
22555
22591
|
let auth;
|
|
22556
22592
|
try {
|
|
22593
|
+
const paymentAuthInput = await resolveAuthorizationInput(
|
|
22594
|
+
request.authorizationProvider,
|
|
22595
|
+
signer,
|
|
22596
|
+
{
|
|
22597
|
+
positionId: request.positionId,
|
|
22598
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
22599
|
+
amount: paymentAmountWei.toString()
|
|
22600
|
+
}
|
|
22601
|
+
);
|
|
22557
22602
|
auth = await generatePaymentAuthorization(
|
|
22558
22603
|
request.positionId,
|
|
22559
22604
|
paymentAmountWei,
|
|
22560
22605
|
chainId,
|
|
22561
|
-
|
|
22606
|
+
paymentAuthInput
|
|
22562
22607
|
);
|
|
22563
22608
|
} catch (authError) {
|
|
22564
22609
|
if (authError.message && authError.message.includes("BigNumber")) {
|
|
@@ -23070,7 +23115,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
23070
23115
|
* @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
|
|
23071
23116
|
* @returns Withdrawal result with transaction details
|
|
23072
23117
|
*/
|
|
23073
|
-
async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount) {
|
|
23118
|
+
async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount, options) {
|
|
23074
23119
|
this.ensureInitialized();
|
|
23075
23120
|
try {
|
|
23076
23121
|
if (this.config.debug) {
|
|
@@ -23285,11 +23330,21 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
23285
23330
|
{}
|
|
23286
23331
|
);
|
|
23287
23332
|
}
|
|
23333
|
+
const withdrawAuthInput = await resolveAuthorizationInput(
|
|
23334
|
+
options?.authorizationProvider,
|
|
23335
|
+
signer,
|
|
23336
|
+
{
|
|
23337
|
+
positionId,
|
|
23338
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
23339
|
+
amount: BigInt(withdrawalAmount).toString(),
|
|
23340
|
+
destinationAddress: withdrawalAddress
|
|
23341
|
+
}
|
|
23342
|
+
);
|
|
23288
23343
|
const auth = await generateWithdrawAuthorization(
|
|
23289
23344
|
positionId,
|
|
23290
23345
|
BigInt(withdrawalAmount),
|
|
23291
23346
|
chainId,
|
|
23292
|
-
|
|
23347
|
+
withdrawAuthInput,
|
|
23293
23348
|
withdrawalAddress
|
|
23294
23349
|
// Pass destination address for message hash
|
|
23295
23350
|
);
|
|
@@ -24363,6 +24418,11 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24363
24418
|
* (`MAX_ATTESTATION_AGE = 1 hour`) and replay-protects via
|
|
24364
24419
|
* `authorizedAt` binding.
|
|
24365
24420
|
*
|
|
24421
|
+
* WHO PAYS: in **service mode** lit-ops-server performs BOTH steps and its
|
|
24422
|
+
* relayer funds the transaction — the borrower is never prompted, because the
|
|
24423
|
+
* Bitcoin withdrawal this cleans up after has already settled. In **direct
|
|
24424
|
+
* mode** (CLI / tests / hardhat) the SDK's own signer submits step 2.
|
|
24425
|
+
*
|
|
24366
24426
|
* `invalidatorTxid` is either:
|
|
24367
24427
|
* - the borrower's own authorized broadcast (classified "consumed-as-authorized"
|
|
24368
24428
|
* by the LIT validator), once it has ≥6 confirmations on the BTC
|
|
@@ -24375,7 +24435,6 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24375
24435
|
async recoverStaleSpend(params) {
|
|
24376
24436
|
this.ensureInitialized();
|
|
24377
24437
|
try {
|
|
24378
|
-
const signer = this.getSignerOrThrow();
|
|
24379
24438
|
const contractAddresses = this.getContractAddressesOrThrow();
|
|
24380
24439
|
const btcSpendAuthorizerAddress = contractAddresses.btcSpendAuthorizer;
|
|
24381
24440
|
if (!btcSpendAuthorizerAddress) {
|
|
@@ -24421,6 +24480,28 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24421
24480
|
success: false,
|
|
24422
24481
|
error: json.error ?? "stale-spend recovery request failed"
|
|
24423
24482
|
};
|
|
24483
|
+
if (!attRes.success || !attRes.attestation) {
|
|
24484
|
+
return {
|
|
24485
|
+
success: false,
|
|
24486
|
+
failedStep: "attestation",
|
|
24487
|
+
error: attRes.error ?? attRes.reason ?? `LIT recovery attestation rejected${attRes.failedStep ? ` at step ${attRes.failedStep}` : ""}`
|
|
24488
|
+
};
|
|
24489
|
+
}
|
|
24490
|
+
if (!attRes.transactionHash && !attRes.alreadyCleared) {
|
|
24491
|
+
return {
|
|
24492
|
+
success: false,
|
|
24493
|
+
failedStep: "submit",
|
|
24494
|
+
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."
|
|
24495
|
+
};
|
|
24496
|
+
}
|
|
24497
|
+
return {
|
|
24498
|
+
success: true,
|
|
24499
|
+
...attRes.transactionHash && {
|
|
24500
|
+
transactionHash: attRes.transactionHash
|
|
24501
|
+
},
|
|
24502
|
+
...attRes.classification && { classification: attRes.classification },
|
|
24503
|
+
attestation: attRes.attestation
|
|
24504
|
+
};
|
|
24424
24505
|
} else {
|
|
24425
24506
|
const rpcUrl = params.rpcUrl ?? this.config.ethRpcUrl;
|
|
24426
24507
|
if (!rpcUrl) {
|
|
@@ -24470,7 +24551,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24470
24551
|
[
|
|
24471
24552
|
"function cancelStaleSpendWithProof(bytes32 positionId, bytes32 utxoKey, uint256 authorizedAt, string calldata invalidatorTxid, uint256 attestationTimestamp, bytes calldata litSignature) external"
|
|
24472
24553
|
],
|
|
24473
|
-
|
|
24554
|
+
this.getSignerOrThrow()
|
|
24474
24555
|
);
|
|
24475
24556
|
const tx = await btcSpendAuthorizer["cancelStaleSpendWithProof"](
|
|
24476
24557
|
attRes.attestation.positionId,
|
|
@@ -25278,10 +25359,22 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25278
25359
|
"getLoanGrant",
|
|
25279
25360
|
data
|
|
25280
25361
|
);
|
|
25362
|
+
const raw = (0, import_ethers17.getBytes)(data);
|
|
25363
|
+
const withdrawScopeSupported = raw.length >= 128;
|
|
25364
|
+
const minWithdrawRatioBps = withdrawScopeSupported ? Number(
|
|
25365
|
+
import_ethers17.AbiCoder.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
|
|
25366
|
+
) : 0;
|
|
25281
25367
|
return {
|
|
25282
25368
|
borrower,
|
|
25283
25369
|
scopeBits: Number(scopeBits),
|
|
25284
|
-
minCollateralRatioBps: Number(minCollateralRatioBps)
|
|
25370
|
+
minCollateralRatioBps: Number(minCollateralRatioBps),
|
|
25371
|
+
minWithdrawRatioBps,
|
|
25372
|
+
/**
|
|
25373
|
+
* True when the deployed registry is v2.1.0+ and therefore honours `SCOPE_WITHDRAW`. The
|
|
25374
|
+
* frontend gates its Withdrawal control on this so the control is absent — not disabled,
|
|
25375
|
+
* not "coming soon" — on a chain whose registry cannot support it.
|
|
25376
|
+
*/
|
|
25377
|
+
withdrawScopeSupported
|
|
25285
25378
|
};
|
|
25286
25379
|
}
|
|
25287
25380
|
/**
|
|
@@ -25323,10 +25416,14 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25323
25416
|
const mintEnabled = hasGrant && (scopes & 4) !== 0;
|
|
25324
25417
|
const floor = grant.minCollateralRatioBps;
|
|
25325
25418
|
const agent = user ? await registry.agentOf(user) : null;
|
|
25419
|
+
const withdrawEnabled = hasGrant && grant.withdrawScopeSupported && (scopes & 8) !== 0;
|
|
25326
25420
|
return {
|
|
25327
25421
|
renewEnabled: hasGrant && (scopes & 1) !== 0,
|
|
25328
25422
|
repayEnabled: hasGrant && (scopes & 2) !== 0,
|
|
25329
25423
|
mintEnabled,
|
|
25424
|
+
withdrawEnabled,
|
|
25425
|
+
withdrawScopeSupported: grant.withdrawScopeSupported,
|
|
25426
|
+
minWithdrawRatioBps: withdrawEnabled ? grant.minWithdrawRatioBps : 0,
|
|
25330
25427
|
minCollateralRatioBps: mintEnabled ? floor : 0,
|
|
25331
25428
|
effectiveMintFloorBps: mintEnabled ? Math.max(floor, protocolMin) : 0,
|
|
25332
25429
|
protocolMinFloorBps: protocolMin,
|
|
@@ -25512,8 +25609,83 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25512
25609
|
const receipt = await tx.wait();
|
|
25513
25610
|
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
|
|
25514
25611
|
}
|
|
25515
|
-
/**
|
|
25516
|
-
|
|
25612
|
+
/**
|
|
25613
|
+
* Grant the agent the WITHDRAW scope for a position (registry v2.1.0+). Borrower-signed.
|
|
25614
|
+
*
|
|
25615
|
+
* CONTRACT WALLETS ONLY, and this is enforced here rather than on-chain. The withdrawal
|
|
25616
|
+
* validator's only non-borrower arm is `checkSafeAgentWithdrawAuthorization`, which requires a
|
|
25617
|
+
* factory-provenanced `AgentModule` whose `safe()` is the borrower — something an EOA cannot
|
|
25618
|
+
* have. The registry deliberately does NOT check wallet type ("Callable by any borrower (this
|
|
25619
|
+
* function does not itself require a Safe)"), so an EOA can record a grant that no code path
|
|
25620
|
+
* will ever satisfy. Refusing here keeps the supported path from writing a dead record.
|
|
25621
|
+
*
|
|
25622
|
+
* That refusal is ergonomics, NOT enforcement — `enableAutoWithdraw` is `external` and reachable
|
|
25623
|
+
* from any wallet. The real reason delegated withdrawal is closed to EOAs is that they can sign
|
|
25624
|
+
* inside the ~44s window themselves, so delegating buys them nothing and only adds risk.
|
|
25625
|
+
*
|
|
25626
|
+
* @param minWithdrawRatioBps Post-withdrawal collateral-ratio floor for AGENT withdrawals.
|
|
25627
|
+
* Clamped by the same governance minimum as the mint floor. **Inert at zero debt** — it
|
|
25628
|
+
* is a ratio, and the post-withdrawal ratio is infinite for any amount once debt is 0.
|
|
25629
|
+
* The operative bound there is the quorum-gated destination allowlist. Do not surface
|
|
25630
|
+
* this to users as a cap on how much an agent may withdraw.
|
|
25631
|
+
* There is no in-place raise: changing it means disable-then-re-enable, deliberately —
|
|
25632
|
+
* on the one scope that moves custodied BTC, incident response can only disable outright.
|
|
25633
|
+
*/
|
|
25634
|
+
async enableAutoWithdraw(positionId, minWithdrawRatioBps, options) {
|
|
25635
|
+
const pid = this.toBytes32(positionId);
|
|
25636
|
+
await this.assertBorrowerIsContractWallet(pid);
|
|
25637
|
+
await this.assertMintFloorAtOrAboveProtocolMin(minWithdrawRatioBps, "withdraw");
|
|
25638
|
+
const { registry, agentAddress } = await this.prepareAgentDelegation(pid, options);
|
|
25639
|
+
const tx = await registry.enableAutoWithdraw(pid, minWithdrawRatioBps);
|
|
25640
|
+
const receipt = await tx.wait();
|
|
25641
|
+
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0, agentAddress };
|
|
25642
|
+
}
|
|
25643
|
+
/**
|
|
25644
|
+
* Revoke the WITHDRAW scope for a position (also zeroes its withdraw floor). Borrower-signed.
|
|
25645
|
+
*
|
|
25646
|
+
* No wallet-type check: revoking is the safe direction, and an EOA that recorded a grant before
|
|
25647
|
+
* this guard existed must be able to clear it.
|
|
25648
|
+
*/
|
|
25649
|
+
async disableAutoWithdraw(positionId) {
|
|
25650
|
+
const addr = this.agentDelegationRegistryOrThrow();
|
|
25651
|
+
const signer = this.getSignerOrThrow();
|
|
25652
|
+
const registry = AgentDelegationRegistry__factory.connect(addr, signer);
|
|
25653
|
+
const pid = this.toBytes32(positionId);
|
|
25654
|
+
const tx = await registry.disableAutoWithdraw(pid);
|
|
25655
|
+
const receipt = await tx.wait();
|
|
25656
|
+
await this.clearGate1IfNoScopesRemain(pid);
|
|
25657
|
+
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
|
|
25658
|
+
}
|
|
25659
|
+
/**
|
|
25660
|
+
* Layer 2 of the withdrawal-delegation gating: refuse to write a grant that could never be
|
|
25661
|
+
* satisfied. See `enableAutoWithdraw` for why this lives here and not in the registry.
|
|
25662
|
+
*/
|
|
25663
|
+
async assertBorrowerIsContractWallet(pid) {
|
|
25664
|
+
const details = await this.getPositionDetailsView(pid);
|
|
25665
|
+
const borrower = details?.borrower;
|
|
25666
|
+
if (!borrower) {
|
|
25667
|
+
throw new SDKError({
|
|
25668
|
+
message: `Could not resolve the borrower for position ${pid} \u2014 refusing to write a delegation grant against an unverified position`,
|
|
25669
|
+
category: "VALIDATION" /* VALIDATION */,
|
|
25670
|
+
severity: "HIGH" /* HIGH */
|
|
25671
|
+
});
|
|
25672
|
+
}
|
|
25673
|
+
const code = await this.getProviderOrThrow().getCode(borrower);
|
|
25674
|
+
if (!code || code === "0x") {
|
|
25675
|
+
throw new SDKError({
|
|
25676
|
+
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.`,
|
|
25677
|
+
category: "VALIDATION" /* VALIDATION */,
|
|
25678
|
+
severity: "MEDIUM" /* MEDIUM */
|
|
25679
|
+
});
|
|
25680
|
+
}
|
|
25681
|
+
}
|
|
25682
|
+
/**
|
|
25683
|
+
* Pre-flight the registry's `FloorBelowProtocolMin` guard with a message a user can act on.
|
|
25684
|
+
*
|
|
25685
|
+
* `agentMintFloorMinBps` is the governance floor-of-floors for BOTH the mint and withdraw
|
|
25686
|
+
* grants — one lever, one invariant — so `scope` only shapes the message.
|
|
25687
|
+
*/
|
|
25688
|
+
async assertMintFloorAtOrAboveProtocolMin(floorBps, scope = "mint") {
|
|
25517
25689
|
if (!Number.isInteger(floorBps) || floorBps <= 0) {
|
|
25518
25690
|
throw new SDKError({
|
|
25519
25691
|
message: `Invalid collateral floor: ${floorBps} bps \u2014 must be a positive integer`,
|
|
@@ -25524,7 +25696,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25524
25696
|
const protocolMin = await this.getAgentMintFloorMinBps();
|
|
25525
25697
|
if (protocolMin === 0) {
|
|
25526
25698
|
throw new SDKError({
|
|
25527
|
-
message:
|
|
25699
|
+
message: `Agent ${scope === "mint" ? "minting" : "withdrawal"} is not configured on this network (agentMintFloorMinBps is 0) \u2014 the registry would reject every ${scope} grant`,
|
|
25528
25700
|
category: "CONFIGURATION" /* CONFIGURATION */,
|
|
25529
25701
|
severity: "HIGH" /* HIGH */
|
|
25530
25702
|
});
|