@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/index.mjs
CHANGED
|
@@ -360,7 +360,7 @@ var init_deployment_addresses = __esm({
|
|
|
360
360
|
CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
|
|
361
361
|
CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
|
|
362
362
|
AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
|
|
363
|
-
AGENT_DELEGATION_REGISTRY_IMPL: "
|
|
363
|
+
AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
|
|
364
364
|
DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
|
|
365
365
|
}
|
|
366
366
|
};
|
|
@@ -630,7 +630,7 @@ var init_deployment_addresses = __esm({
|
|
|
630
630
|
LOCALHOST_DEPLOYMENT = {
|
|
631
631
|
network: "localhost",
|
|
632
632
|
chainId: 1337,
|
|
633
|
-
timestamp: "2026-07-
|
|
633
|
+
timestamp: "2026-07-20T19:45:58.514Z",
|
|
634
634
|
deployer: "",
|
|
635
635
|
contracts: {
|
|
636
636
|
MessageHashBuilder: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
|
|
@@ -650,30 +650,6 @@ var init_deployment_addresses = __esm({
|
|
|
650
650
|
PositionManager: "0x851356ae760d987E095750cCeb3bC6014560891C",
|
|
651
651
|
OperationAuthorizationRegistry: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
|
|
652
652
|
PKPValidation: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A"
|
|
653
|
-
},
|
|
654
|
-
latestEnv: {
|
|
655
|
-
UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
656
|
-
UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
|
|
657
|
-
POSITION_MANAGER: "0x851356ae760d987E095750cCeb3bC6014560891C",
|
|
658
|
-
PKP_VALIDATION_REGISTRY: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A",
|
|
659
|
-
PKP_VALIDATION_CID_V1: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
|
|
660
|
-
PKP_VALIDATION_CID_V3: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
|
|
661
|
-
PKP_ETH_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
662
|
-
OPERATION_AUTHORIZATION_REGISTRY: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
|
|
663
|
-
UCD_MINT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
664
|
-
UCD_MINT_VALIDATOR_VERSION: 1,
|
|
665
|
-
BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
666
|
-
BTC_WITHDRAWAL_VALIDATOR_VERSION: 3,
|
|
667
|
-
UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
668
|
-
UPDATE_BALANCE_VALIDATOR_VERSION: 1,
|
|
669
|
-
PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
670
|
-
PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
|
|
671
|
-
EXTEND_POSITION_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
672
|
-
EXTEND_POSITION_VALIDATOR_VERSION: 1,
|
|
673
|
-
POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
|
|
674
|
-
LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
|
|
675
|
-
TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
|
|
676
|
-
COMMUNITY_MANAGER_MODULE: ""
|
|
677
653
|
}
|
|
678
654
|
};
|
|
679
655
|
LOCALHOST_CONTRACTS = {
|
|
@@ -5528,8 +5504,14 @@ function getMainnetConfig() {
|
|
|
5528
5504
|
agentModuleFactory: MAINNET_CONTRACTS.AgentModuleFactory || ""
|
|
5529
5505
|
},
|
|
5530
5506
|
subgraphs: {
|
|
5507
|
+
// KNOWN-WRONG placeholder (see GOAL-PLAN step 2 / dogfood F-CLI-4): this is a
|
|
5508
|
+
// SEPOLIA subgraph id in a mainnet (chainId 1) config, and this gateway host
|
|
5509
|
+
// needs an Authorization key the SDK does not (and must not) hold — so the
|
|
5510
|
+
// URL is doubly unusable. The `CCTPsd…` path segment is the subgraph's
|
|
5511
|
+
// PUBLIC ID, not a credential. The fix is a chain-correct SERVER-side proxy
|
|
5512
|
+
// (see mcp/docs/SUBGRAPH-PROXY-PLAN.md) — same rule as rpcUrls above:
|
|
5513
|
+
// never ship an API-keyed URL in a client config.
|
|
5531
5514
|
diamondHandsUrl: "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/CCTPsdYqco2jChDLLBQTbdJWwoukVoMt1cXeR9ti6r9A"
|
|
5532
|
-
// Published Sepolia subgraph on Arbitrum One
|
|
5533
5515
|
},
|
|
5534
5516
|
litNetwork: "chipotle",
|
|
5535
5517
|
debug: false
|
|
@@ -6326,7 +6308,7 @@ async function generateMintAuthorization(positionId, amount, chainId, signerOrPr
|
|
|
6326
6308
|
signature
|
|
6327
6309
|
};
|
|
6328
6310
|
}
|
|
6329
|
-
async function generatePaymentAuthorization(positionId, amount, chainId,
|
|
6311
|
+
async function generatePaymentAuthorization(positionId, amount, chainId, signerOrPrecomputed) {
|
|
6330
6312
|
if (typeof positionId !== "string") {
|
|
6331
6313
|
throw new Error(`positionId must be a string, got ${typeof positionId}`);
|
|
6332
6314
|
}
|
|
@@ -6336,6 +6318,18 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signer)
|
|
|
6336
6318
|
if (typeof chainId !== "number") {
|
|
6337
6319
|
throw new Error(`chainId must be a number, got ${typeof chainId}`);
|
|
6338
6320
|
}
|
|
6321
|
+
if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
|
|
6322
|
+
const { timestamp: timestamp2, signature: signature2 } = signerOrPrecomputed;
|
|
6323
|
+
return {
|
|
6324
|
+
positionId,
|
|
6325
|
+
timestamp: timestamp2,
|
|
6326
|
+
chainId,
|
|
6327
|
+
amount: amount.toString(),
|
|
6328
|
+
action: "make-payment",
|
|
6329
|
+
signature: signature2
|
|
6330
|
+
};
|
|
6331
|
+
}
|
|
6332
|
+
const signer = signerOrPrecomputed;
|
|
6339
6333
|
const timestamp = await calculateNextQuantumTimestamp();
|
|
6340
6334
|
if (typeof timestamp !== "number") {
|
|
6341
6335
|
throw new Error(`timestamp must be a number, got ${typeof timestamp}`);
|
|
@@ -6577,6 +6571,26 @@ async function generateExtendAuthorization(positionId, newTerm, chainId, signerO
|
|
|
6577
6571
|
};
|
|
6578
6572
|
}
|
|
6579
6573
|
|
|
6574
|
+
// src/utils/authorization-provider.utils.ts
|
|
6575
|
+
async function resolveAuthorizationInput(provider, signer, ctx) {
|
|
6576
|
+
if (!provider)
|
|
6577
|
+
return signer;
|
|
6578
|
+
const result = await provider(ctx);
|
|
6579
|
+
if (!result || typeof result.signature !== "string" || result.signature.length === 0) {
|
|
6580
|
+
throw new Error(
|
|
6581
|
+
"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"
|
|
6582
|
+
);
|
|
6583
|
+
}
|
|
6584
|
+
if (!Number.isInteger(result.timestamp)) {
|
|
6585
|
+
throw new Error(
|
|
6586
|
+
`authorizationProvider returned a non-integer timestamp (${String(
|
|
6587
|
+
result.timestamp
|
|
6588
|
+
)}) \u2014 the protocol call must carry the same value the envelope was signed over`
|
|
6589
|
+
);
|
|
6590
|
+
}
|
|
6591
|
+
return { timestamp: result.timestamp, signature: result.signature };
|
|
6592
|
+
}
|
|
6593
|
+
|
|
6580
6594
|
// src/utils/eip712-login.ts
|
|
6581
6595
|
import { hexlify, randomBytes } from "ethers";
|
|
6582
6596
|
function buildLoginDomain(chainId) {
|
|
@@ -20002,11 +20016,20 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20002
20016
|
{}
|
|
20003
20017
|
);
|
|
20004
20018
|
}
|
|
20019
|
+
const mintAuthInput = await resolveAuthorizationInput(
|
|
20020
|
+
request.authorizationProvider,
|
|
20021
|
+
signer2,
|
|
20022
|
+
{
|
|
20023
|
+
positionId: request.positionId,
|
|
20024
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
20025
|
+
amount: requestAmountWei.toString()
|
|
20026
|
+
}
|
|
20027
|
+
);
|
|
20005
20028
|
const auth = await generateMintAuthorization(
|
|
20006
20029
|
request.positionId,
|
|
20007
20030
|
BigInt(requestAmountWei.toString()),
|
|
20008
20031
|
chainId,
|
|
20009
|
-
|
|
20032
|
+
mintAuthInput
|
|
20010
20033
|
);
|
|
20011
20034
|
if (this.config.debug) {
|
|
20012
20035
|
log.info(` Authorization generated (attempt ${attempt})`, {});
|
|
@@ -21597,7 +21620,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
21597
21620
|
* @param _selectedTerm - Extension term in months
|
|
21598
21621
|
* @returns Transaction receipt
|
|
21599
21622
|
*/
|
|
21600
|
-
async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl) {
|
|
21623
|
+
async extendPosition(_positionId, _selectedTerm, _rpcUrl, _bitcoinRpcUrl, _authorizationProvider) {
|
|
21601
21624
|
this.ensureInitialized();
|
|
21602
21625
|
if (typeof _positionId !== "string") {
|
|
21603
21626
|
throw new Error(`positionId must be a string, got ${typeof _positionId}`);
|
|
@@ -21691,11 +21714,23 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
21691
21714
|
}
|
|
21692
21715
|
}
|
|
21693
21716
|
const signer = this.getSignerOrThrow();
|
|
21717
|
+
const extendAuthInput = await resolveAuthorizationInput(
|
|
21718
|
+
_authorizationProvider,
|
|
21719
|
+
signer,
|
|
21720
|
+
{
|
|
21721
|
+
positionId: _positionId,
|
|
21722
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
21723
|
+
// The extend envelope binds the TERM, not an amount. Carried as "0" so
|
|
21724
|
+
// the context shape stays uniform across the four operations.
|
|
21725
|
+
amount: "0",
|
|
21726
|
+
selectedTerm: _selectedTerm
|
|
21727
|
+
}
|
|
21728
|
+
);
|
|
21694
21729
|
const auth = await generateExtendAuthorization(
|
|
21695
21730
|
_positionId,
|
|
21696
21731
|
_selectedTerm,
|
|
21697
21732
|
chainId,
|
|
21698
|
-
|
|
21733
|
+
extendAuthInput
|
|
21699
21734
|
);
|
|
21700
21735
|
if (this.config.debug) {
|
|
21701
21736
|
log.info(" Extend authorization generated", {
|
|
@@ -21951,7 +21986,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
21951
21986
|
positionId,
|
|
21952
21987
|
selectedTerm,
|
|
21953
21988
|
request.rpcUrl,
|
|
21954
|
-
request.customBitcoinRpcUrl
|
|
21989
|
+
request.customBitcoinRpcUrl,
|
|
21990
|
+
request.authorizationProvider
|
|
21955
21991
|
);
|
|
21956
21992
|
let newExpiryAt;
|
|
21957
21993
|
try {
|
|
@@ -22479,11 +22515,20 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
22479
22515
|
}
|
|
22480
22516
|
let auth;
|
|
22481
22517
|
try {
|
|
22518
|
+
const paymentAuthInput = await resolveAuthorizationInput(
|
|
22519
|
+
request.authorizationProvider,
|
|
22520
|
+
signer,
|
|
22521
|
+
{
|
|
22522
|
+
positionId: request.positionId,
|
|
22523
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
22524
|
+
amount: paymentAmountWei.toString()
|
|
22525
|
+
}
|
|
22526
|
+
);
|
|
22482
22527
|
auth = await generatePaymentAuthorization(
|
|
22483
22528
|
request.positionId,
|
|
22484
22529
|
paymentAmountWei,
|
|
22485
22530
|
chainId,
|
|
22486
|
-
|
|
22531
|
+
paymentAuthInput
|
|
22487
22532
|
);
|
|
22488
22533
|
} catch (authError) {
|
|
22489
22534
|
if (authError.message && authError.message.includes("BigNumber")) {
|
|
@@ -22995,7 +23040,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
22995
23040
|
* @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
|
|
22996
23041
|
* @returns Withdrawal result with transaction details
|
|
22997
23042
|
*/
|
|
22998
|
-
async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount) {
|
|
23043
|
+
async withdrawBTC(positionId, withdrawalAddress, withdrawalAmount, options) {
|
|
22999
23044
|
this.ensureInitialized();
|
|
23000
23045
|
try {
|
|
23001
23046
|
if (this.config.debug) {
|
|
@@ -23210,11 +23255,21 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
23210
23255
|
{}
|
|
23211
23256
|
);
|
|
23212
23257
|
}
|
|
23258
|
+
const withdrawAuthInput = await resolveAuthorizationInput(
|
|
23259
|
+
options?.authorizationProvider,
|
|
23260
|
+
signer,
|
|
23261
|
+
{
|
|
23262
|
+
positionId,
|
|
23263
|
+
timestamp: calculateNextQuantumTimestamp(),
|
|
23264
|
+
amount: BigInt(withdrawalAmount).toString(),
|
|
23265
|
+
destinationAddress: withdrawalAddress
|
|
23266
|
+
}
|
|
23267
|
+
);
|
|
23213
23268
|
const auth = await generateWithdrawAuthorization(
|
|
23214
23269
|
positionId,
|
|
23215
23270
|
BigInt(withdrawalAmount),
|
|
23216
23271
|
chainId,
|
|
23217
|
-
|
|
23272
|
+
withdrawAuthInput,
|
|
23218
23273
|
withdrawalAddress
|
|
23219
23274
|
// Pass destination address for message hash
|
|
23220
23275
|
);
|
|
@@ -24288,6 +24343,11 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24288
24343
|
* (`MAX_ATTESTATION_AGE = 1 hour`) and replay-protects via
|
|
24289
24344
|
* `authorizedAt` binding.
|
|
24290
24345
|
*
|
|
24346
|
+
* WHO PAYS: in **service mode** lit-ops-server performs BOTH steps and its
|
|
24347
|
+
* relayer funds the transaction — the borrower is never prompted, because the
|
|
24348
|
+
* Bitcoin withdrawal this cleans up after has already settled. In **direct
|
|
24349
|
+
* mode** (CLI / tests / hardhat) the SDK's own signer submits step 2.
|
|
24350
|
+
*
|
|
24291
24351
|
* `invalidatorTxid` is either:
|
|
24292
24352
|
* - the borrower's own authorized broadcast (classified "consumed-as-authorized"
|
|
24293
24353
|
* by the LIT validator), once it has ≥6 confirmations on the BTC
|
|
@@ -24300,7 +24360,6 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24300
24360
|
async recoverStaleSpend(params) {
|
|
24301
24361
|
this.ensureInitialized();
|
|
24302
24362
|
try {
|
|
24303
|
-
const signer = this.getSignerOrThrow();
|
|
24304
24363
|
const contractAddresses = this.getContractAddressesOrThrow();
|
|
24305
24364
|
const btcSpendAuthorizerAddress = contractAddresses.btcSpendAuthorizer;
|
|
24306
24365
|
if (!btcSpendAuthorizerAddress) {
|
|
@@ -24346,6 +24405,28 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24346
24405
|
success: false,
|
|
24347
24406
|
error: json.error ?? "stale-spend recovery request failed"
|
|
24348
24407
|
};
|
|
24408
|
+
if (!attRes.success || !attRes.attestation) {
|
|
24409
|
+
return {
|
|
24410
|
+
success: false,
|
|
24411
|
+
failedStep: "attestation",
|
|
24412
|
+
error: attRes.error ?? attRes.reason ?? `LIT recovery attestation rejected${attRes.failedStep ? ` at step ${attRes.failedStep}` : ""}`
|
|
24413
|
+
};
|
|
24414
|
+
}
|
|
24415
|
+
if (!attRes.transactionHash && !attRes.alreadyCleared) {
|
|
24416
|
+
return {
|
|
24417
|
+
success: false,
|
|
24418
|
+
failedStep: "submit",
|
|
24419
|
+
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."
|
|
24420
|
+
};
|
|
24421
|
+
}
|
|
24422
|
+
return {
|
|
24423
|
+
success: true,
|
|
24424
|
+
...attRes.transactionHash && {
|
|
24425
|
+
transactionHash: attRes.transactionHash
|
|
24426
|
+
},
|
|
24427
|
+
...attRes.classification && { classification: attRes.classification },
|
|
24428
|
+
attestation: attRes.attestation
|
|
24429
|
+
};
|
|
24349
24430
|
} else {
|
|
24350
24431
|
const rpcUrl = params.rpcUrl ?? this.config.ethRpcUrl;
|
|
24351
24432
|
if (!rpcUrl) {
|
|
@@ -24395,7 +24476,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24395
24476
|
[
|
|
24396
24477
|
"function cancelStaleSpendWithProof(bytes32 positionId, bytes32 utxoKey, uint256 authorizedAt, string calldata invalidatorTxid, uint256 attestationTimestamp, bytes calldata litSignature) external"
|
|
24397
24478
|
],
|
|
24398
|
-
|
|
24479
|
+
this.getSignerOrThrow()
|
|
24399
24480
|
);
|
|
24400
24481
|
const tx = await btcSpendAuthorizer["cancelStaleSpendWithProof"](
|
|
24401
24482
|
attRes.attestation.positionId,
|
|
@@ -25203,10 +25284,22 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25203
25284
|
"getLoanGrant",
|
|
25204
25285
|
data
|
|
25205
25286
|
);
|
|
25287
|
+
const raw = getBytes5(data);
|
|
25288
|
+
const withdrawScopeSupported = raw.length >= 128;
|
|
25289
|
+
const minWithdrawRatioBps = withdrawScopeSupported ? Number(
|
|
25290
|
+
AbiCoder2.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
|
|
25291
|
+
) : 0;
|
|
25206
25292
|
return {
|
|
25207
25293
|
borrower,
|
|
25208
25294
|
scopeBits: Number(scopeBits),
|
|
25209
|
-
minCollateralRatioBps: Number(minCollateralRatioBps)
|
|
25295
|
+
minCollateralRatioBps: Number(minCollateralRatioBps),
|
|
25296
|
+
minWithdrawRatioBps,
|
|
25297
|
+
/**
|
|
25298
|
+
* True when the deployed registry is v2.1.0+ and therefore honours `SCOPE_WITHDRAW`. The
|
|
25299
|
+
* frontend gates its Withdrawal control on this so the control is absent — not disabled,
|
|
25300
|
+
* not "coming soon" — on a chain whose registry cannot support it.
|
|
25301
|
+
*/
|
|
25302
|
+
withdrawScopeSupported
|
|
25210
25303
|
};
|
|
25211
25304
|
}
|
|
25212
25305
|
/**
|
|
@@ -25248,10 +25341,14 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25248
25341
|
const mintEnabled = hasGrant && (scopes & 4) !== 0;
|
|
25249
25342
|
const floor = grant.minCollateralRatioBps;
|
|
25250
25343
|
const agent = user ? await registry.agentOf(user) : null;
|
|
25344
|
+
const withdrawEnabled = hasGrant && grant.withdrawScopeSupported && (scopes & 8) !== 0;
|
|
25251
25345
|
return {
|
|
25252
25346
|
renewEnabled: hasGrant && (scopes & 1) !== 0,
|
|
25253
25347
|
repayEnabled: hasGrant && (scopes & 2) !== 0,
|
|
25254
25348
|
mintEnabled,
|
|
25349
|
+
withdrawEnabled,
|
|
25350
|
+
withdrawScopeSupported: grant.withdrawScopeSupported,
|
|
25351
|
+
minWithdrawRatioBps: withdrawEnabled ? grant.minWithdrawRatioBps : 0,
|
|
25255
25352
|
minCollateralRatioBps: mintEnabled ? floor : 0,
|
|
25256
25353
|
effectiveMintFloorBps: mintEnabled ? Math.max(floor, protocolMin) : 0,
|
|
25257
25354
|
protocolMinFloorBps: protocolMin,
|
|
@@ -25437,8 +25534,83 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25437
25534
|
const receipt = await tx.wait();
|
|
25438
25535
|
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
|
|
25439
25536
|
}
|
|
25440
|
-
/**
|
|
25441
|
-
|
|
25537
|
+
/**
|
|
25538
|
+
* Grant the agent the WITHDRAW scope for a position (registry v2.1.0+). Borrower-signed.
|
|
25539
|
+
*
|
|
25540
|
+
* CONTRACT WALLETS ONLY, and this is enforced here rather than on-chain. The withdrawal
|
|
25541
|
+
* validator's only non-borrower arm is `checkSafeAgentWithdrawAuthorization`, which requires a
|
|
25542
|
+
* factory-provenanced `AgentModule` whose `safe()` is the borrower — something an EOA cannot
|
|
25543
|
+
* have. The registry deliberately does NOT check wallet type ("Callable by any borrower (this
|
|
25544
|
+
* function does not itself require a Safe)"), so an EOA can record a grant that no code path
|
|
25545
|
+
* will ever satisfy. Refusing here keeps the supported path from writing a dead record.
|
|
25546
|
+
*
|
|
25547
|
+
* That refusal is ergonomics, NOT enforcement — `enableAutoWithdraw` is `external` and reachable
|
|
25548
|
+
* from any wallet. The real reason delegated withdrawal is closed to EOAs is that they can sign
|
|
25549
|
+
* inside the ~44s window themselves, so delegating buys them nothing and only adds risk.
|
|
25550
|
+
*
|
|
25551
|
+
* @param minWithdrawRatioBps Post-withdrawal collateral-ratio floor for AGENT withdrawals.
|
|
25552
|
+
* Clamped by the same governance minimum as the mint floor. **Inert at zero debt** — it
|
|
25553
|
+
* is a ratio, and the post-withdrawal ratio is infinite for any amount once debt is 0.
|
|
25554
|
+
* The operative bound there is the quorum-gated destination allowlist. Do not surface
|
|
25555
|
+
* this to users as a cap on how much an agent may withdraw.
|
|
25556
|
+
* There is no in-place raise: changing it means disable-then-re-enable, deliberately —
|
|
25557
|
+
* on the one scope that moves custodied BTC, incident response can only disable outright.
|
|
25558
|
+
*/
|
|
25559
|
+
async enableAutoWithdraw(positionId, minWithdrawRatioBps, options) {
|
|
25560
|
+
const pid = this.toBytes32(positionId);
|
|
25561
|
+
await this.assertBorrowerIsContractWallet(pid);
|
|
25562
|
+
await this.assertMintFloorAtOrAboveProtocolMin(minWithdrawRatioBps, "withdraw");
|
|
25563
|
+
const { registry, agentAddress } = await this.prepareAgentDelegation(pid, options);
|
|
25564
|
+
const tx = await registry.enableAutoWithdraw(pid, minWithdrawRatioBps);
|
|
25565
|
+
const receipt = await tx.wait();
|
|
25566
|
+
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0, agentAddress };
|
|
25567
|
+
}
|
|
25568
|
+
/**
|
|
25569
|
+
* Revoke the WITHDRAW scope for a position (also zeroes its withdraw floor). Borrower-signed.
|
|
25570
|
+
*
|
|
25571
|
+
* No wallet-type check: revoking is the safe direction, and an EOA that recorded a grant before
|
|
25572
|
+
* this guard existed must be able to clear it.
|
|
25573
|
+
*/
|
|
25574
|
+
async disableAutoWithdraw(positionId) {
|
|
25575
|
+
const addr = this.agentDelegationRegistryOrThrow();
|
|
25576
|
+
const signer = this.getSignerOrThrow();
|
|
25577
|
+
const registry = AgentDelegationRegistry__factory.connect(addr, signer);
|
|
25578
|
+
const pid = this.toBytes32(positionId);
|
|
25579
|
+
const tx = await registry.disableAutoWithdraw(pid);
|
|
25580
|
+
const receipt = await tx.wait();
|
|
25581
|
+
await this.clearGate1IfNoScopesRemain(pid);
|
|
25582
|
+
return { hash: tx.hash, blockNumber: receipt?.blockNumber ?? 0 };
|
|
25583
|
+
}
|
|
25584
|
+
/**
|
|
25585
|
+
* Layer 2 of the withdrawal-delegation gating: refuse to write a grant that could never be
|
|
25586
|
+
* satisfied. See `enableAutoWithdraw` for why this lives here and not in the registry.
|
|
25587
|
+
*/
|
|
25588
|
+
async assertBorrowerIsContractWallet(pid) {
|
|
25589
|
+
const details = await this.getPositionDetailsView(pid);
|
|
25590
|
+
const borrower = details?.borrower;
|
|
25591
|
+
if (!borrower) {
|
|
25592
|
+
throw new SDKError({
|
|
25593
|
+
message: `Could not resolve the borrower for position ${pid} \u2014 refusing to write a delegation grant against an unverified position`,
|
|
25594
|
+
category: "VALIDATION" /* VALIDATION */,
|
|
25595
|
+
severity: "HIGH" /* HIGH */
|
|
25596
|
+
});
|
|
25597
|
+
}
|
|
25598
|
+
const code = await this.getProviderOrThrow().getCode(borrower);
|
|
25599
|
+
if (!code || code === "0x") {
|
|
25600
|
+
throw new SDKError({
|
|
25601
|
+
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.`,
|
|
25602
|
+
category: "VALIDATION" /* VALIDATION */,
|
|
25603
|
+
severity: "MEDIUM" /* MEDIUM */
|
|
25604
|
+
});
|
|
25605
|
+
}
|
|
25606
|
+
}
|
|
25607
|
+
/**
|
|
25608
|
+
* Pre-flight the registry's `FloorBelowProtocolMin` guard with a message a user can act on.
|
|
25609
|
+
*
|
|
25610
|
+
* `agentMintFloorMinBps` is the governance floor-of-floors for BOTH the mint and withdraw
|
|
25611
|
+
* grants — one lever, one invariant — so `scope` only shapes the message.
|
|
25612
|
+
*/
|
|
25613
|
+
async assertMintFloorAtOrAboveProtocolMin(floorBps, scope = "mint") {
|
|
25442
25614
|
if (!Number.isInteger(floorBps) || floorBps <= 0) {
|
|
25443
25615
|
throw new SDKError({
|
|
25444
25616
|
message: `Invalid collateral floor: ${floorBps} bps \u2014 must be a positive integer`,
|
|
@@ -25449,7 +25621,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25449
25621
|
const protocolMin = await this.getAgentMintFloorMinBps();
|
|
25450
25622
|
if (protocolMin === 0) {
|
|
25451
25623
|
throw new SDKError({
|
|
25452
|
-
message:
|
|
25624
|
+
message: `Agent ${scope === "mint" ? "minting" : "withdrawal"} is not configured on this network (agentMintFloorMinBps is 0) \u2014 the registry would reject every ${scope} grant`,
|
|
25453
25625
|
category: "CONFIGURATION" /* CONFIGURATION */,
|
|
25454
25626
|
severity: "HIGH" /* HIGH */
|
|
25455
25627
|
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Loan Operations Interfaces
|
|
3
3
|
*/
|
|
4
4
|
import { LoanStatus } from "../../types/loanStatus";
|
|
5
|
+
import type { AuthorizationProvider } from "../../utils/authorization-provider.utils";
|
|
5
6
|
export type BitcoinAddresses = {
|
|
6
7
|
mainnet: string;
|
|
7
8
|
testnet: string;
|
|
@@ -176,6 +177,18 @@ export interface UCDMintRequest {
|
|
|
176
177
|
stubbedAvailableBtcSats?: string;
|
|
177
178
|
stubbedAuthorizedSpendsHash?: string;
|
|
178
179
|
};
|
|
180
|
+
/**
|
|
181
|
+
* Supplies the borrower authorization envelope instead of the connected
|
|
182
|
+
* signer — the seam a delegated Safe uses so its agent signs instantly
|
|
183
|
+
* rather than the SDK asking for an owner quorum inside a quantum window.
|
|
184
|
+
*
|
|
185
|
+
* Omit it and nothing changes: the SDK signs with the connected signer
|
|
186
|
+
* exactly as before, which is what every EOA borrower does.
|
|
187
|
+
*
|
|
188
|
+
* See `utils/authorization-provider.utils.ts` for why this is a callback and
|
|
189
|
+
* not a `{ timestamp, signature }` value.
|
|
190
|
+
*/
|
|
191
|
+
authorizationProvider?: AuthorizationProvider;
|
|
179
192
|
}
|
|
180
193
|
/**
|
|
181
194
|
* UCD Mint Result Interface
|
|
@@ -213,6 +226,18 @@ export interface RenewPositionResult {
|
|
|
213
226
|
export interface RenewPositionRequest {
|
|
214
227
|
positionId: string;
|
|
215
228
|
selectedTerm: number;
|
|
229
|
+
/**
|
|
230
|
+
* Supplies the borrower authorization envelope instead of the connected
|
|
231
|
+
* signer — the seam a delegated Safe uses so its agent signs instantly
|
|
232
|
+
* rather than the SDK asking for an owner quorum inside a quantum window.
|
|
233
|
+
*
|
|
234
|
+
* Omit it and nothing changes: the SDK signs with the connected signer
|
|
235
|
+
* exactly as before, which is what every EOA borrower does.
|
|
236
|
+
*
|
|
237
|
+
* See `utils/authorization-provider.utils.ts` for why this is a callback and
|
|
238
|
+
* not a `{ timestamp, signature }` value.
|
|
239
|
+
*/
|
|
240
|
+
authorizationProvider?: AuthorizationProvider;
|
|
216
241
|
}
|
|
217
242
|
/**
|
|
218
243
|
* BTC Withdrawal Result Interface
|
|
@@ -282,6 +307,18 @@ export interface PartialPaymentRequest {
|
|
|
282
307
|
positionId: string;
|
|
283
308
|
paymentAmount: number;
|
|
284
309
|
rpcUrl?: string;
|
|
310
|
+
/**
|
|
311
|
+
* Supplies the borrower authorization envelope instead of the connected
|
|
312
|
+
* signer — the seam a delegated Safe uses so its agent signs instantly
|
|
313
|
+
* rather than the SDK asking for an owner quorum inside a quantum window.
|
|
314
|
+
*
|
|
315
|
+
* Omit it and nothing changes: the SDK signs with the connected signer
|
|
316
|
+
* exactly as before, which is what every EOA borrower does.
|
|
317
|
+
*
|
|
318
|
+
* See `utils/authorization-provider.utils.ts` for why this is a callback and
|
|
319
|
+
* not a `{ timestamp, signature }` value.
|
|
320
|
+
*/
|
|
321
|
+
authorizationProvider?: AuthorizationProvider;
|
|
285
322
|
}
|
|
286
323
|
/**
|
|
287
324
|
* Confirm Balance Result Interface
|
|
@@ -18,6 +18,7 @@ import { SDKError } from "../utils/error-handler";
|
|
|
18
18
|
import type { CreateLoanRequest, CreateLoanResult, LoanDataDetail, UCDMintRequest, UCDMintResult, PartialPaymentRequest, PartialPaymentResult, BTCWithdrawalResult, RenewPositionRequest, RenewPositionResult, LiquidationRequest, LiquidationResult, ConfirmBalanceRequest, ConfirmBalanceResult, TermsWithFeesResult } from "../interfaces/chunks/loan-operations.i";
|
|
19
19
|
import type { DiamondHandsSDKConfig } from "../interfaces/chunks/config.i";
|
|
20
20
|
import type { PKPData } from "../interfaces/chunks/pkp-integration.i";
|
|
21
|
+
import { type AuthorizationProvider } from "../utils/authorization-provider.utils";
|
|
21
22
|
import type { DhServerLoginPayload } from "../utils/eip712-login";
|
|
22
23
|
import { type ReconciledWithdrawal } from "../utils/withdrawal-reconciliation.utils";
|
|
23
24
|
import { ContractManager } from "./contract/contract-manager.module";
|
|
@@ -581,7 +582,15 @@ export declare class DiamondHandsSDK {
|
|
|
581
582
|
* @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
|
|
582
583
|
* @returns Withdrawal result with transaction details
|
|
583
584
|
*/
|
|
584
|
-
withdrawBTC(positionId: string, withdrawalAddress: string, withdrawalAmount: number
|
|
585
|
+
withdrawBTC(positionId: string, withdrawalAddress: string, withdrawalAmount: number,
|
|
586
|
+
/**
|
|
587
|
+
* An options bag rather than a fifth positional argument: this method is
|
|
588
|
+
* already three positional strings/numbers deep, and the next caller to
|
|
589
|
+
* add one would have to guess the order.
|
|
590
|
+
*/
|
|
591
|
+
options?: {
|
|
592
|
+
authorizationProvider?: AuthorizationProvider;
|
|
593
|
+
}): Promise<BTCWithdrawalResult>;
|
|
585
594
|
/**
|
|
586
595
|
* TEMPORARY (multi-UTXO withdrawal fix, Phase A): fetch the vault's confirmed
|
|
587
596
|
* UTXO set from lit-ops-server (`GET /api/lit/vault-utxos`) so the caller can
|
|
@@ -739,6 +748,11 @@ export declare class DiamondHandsSDK {
|
|
|
739
748
|
* (`MAX_ATTESTATION_AGE = 1 hour`) and replay-protects via
|
|
740
749
|
* `authorizedAt` binding.
|
|
741
750
|
*
|
|
751
|
+
* WHO PAYS: in **service mode** lit-ops-server performs BOTH steps and its
|
|
752
|
+
* relayer funds the transaction — the borrower is never prompted, because the
|
|
753
|
+
* Bitcoin withdrawal this cleans up after has already settled. In **direct
|
|
754
|
+
* mode** (CLI / tests / hardhat) the SDK's own signer submits step 2.
|
|
755
|
+
*
|
|
742
756
|
* `invalidatorTxid` is either:
|
|
743
757
|
* - the borrower's own authorized broadcast (classified "consumed-as-authorized"
|
|
744
758
|
* by the LIT validator), once it has ≥6 confirmations on the BTC
|
|
@@ -1071,6 +1085,16 @@ export declare class DiamondHandsSDK {
|
|
|
1071
1085
|
agentActive: boolean | null;
|
|
1072
1086
|
/** Agent expiry (unix seconds) — the ONLY time bound on every grant. Null without `user`. */
|
|
1073
1087
|
agentValidUntil: number | null;
|
|
1088
|
+
/** SCOPE_WITHDRAW granted. Always false where the registry predates v2.1.0. */
|
|
1089
|
+
withdrawEnabled: boolean;
|
|
1090
|
+
/** Does the DEPLOYED registry honour SCOPE_WITHDRAW at all (v2.1.0+)? */
|
|
1091
|
+
withdrawScopeSupported: boolean;
|
|
1092
|
+
/**
|
|
1093
|
+
* Grant's post-withdrawal collateral floor in bps; 0 when WITHDRAW is not granted.
|
|
1094
|
+
* INERT AT ZERO DEBT — a ratio cannot bound a withdrawal once debt is 0. Never present this
|
|
1095
|
+
* as a cap on how much an agent may withdraw.
|
|
1096
|
+
*/
|
|
1097
|
+
minWithdrawRatioBps: number;
|
|
1074
1098
|
}>;
|
|
1075
1099
|
/** Governance floor-of-floors for agent mints (bps). The UI's minimum for the floor editor. */
|
|
1076
1100
|
getAgentMintFloorMinBps(): Promise<number>;
|
|
@@ -1161,7 +1185,56 @@ export declare class DiamondHandsSDK {
|
|
|
1161
1185
|
hash: string;
|
|
1162
1186
|
blockNumber: number;
|
|
1163
1187
|
}>;
|
|
1164
|
-
/**
|
|
1188
|
+
/**
|
|
1189
|
+
* Grant the agent the WITHDRAW scope for a position (registry v2.1.0+). Borrower-signed.
|
|
1190
|
+
*
|
|
1191
|
+
* CONTRACT WALLETS ONLY, and this is enforced here rather than on-chain. The withdrawal
|
|
1192
|
+
* validator's only non-borrower arm is `checkSafeAgentWithdrawAuthorization`, which requires a
|
|
1193
|
+
* factory-provenanced `AgentModule` whose `safe()` is the borrower — something an EOA cannot
|
|
1194
|
+
* have. The registry deliberately does NOT check wallet type ("Callable by any borrower (this
|
|
1195
|
+
* function does not itself require a Safe)"), so an EOA can record a grant that no code path
|
|
1196
|
+
* will ever satisfy. Refusing here keeps the supported path from writing a dead record.
|
|
1197
|
+
*
|
|
1198
|
+
* That refusal is ergonomics, NOT enforcement — `enableAutoWithdraw` is `external` and reachable
|
|
1199
|
+
* from any wallet. The real reason delegated withdrawal is closed to EOAs is that they can sign
|
|
1200
|
+
* inside the ~44s window themselves, so delegating buys them nothing and only adds risk.
|
|
1201
|
+
*
|
|
1202
|
+
* @param minWithdrawRatioBps Post-withdrawal collateral-ratio floor for AGENT withdrawals.
|
|
1203
|
+
* Clamped by the same governance minimum as the mint floor. **Inert at zero debt** — it
|
|
1204
|
+
* is a ratio, and the post-withdrawal ratio is infinite for any amount once debt is 0.
|
|
1205
|
+
* The operative bound there is the quorum-gated destination allowlist. Do not surface
|
|
1206
|
+
* this to users as a cap on how much an agent may withdraw.
|
|
1207
|
+
* There is no in-place raise: changing it means disable-then-re-enable, deliberately —
|
|
1208
|
+
* on the one scope that moves custodied BTC, incident response can only disable outright.
|
|
1209
|
+
*/
|
|
1210
|
+
enableAutoWithdraw(positionId: string, minWithdrawRatioBps: number, options?: {
|
|
1211
|
+
agentValiditySeconds?: number;
|
|
1212
|
+
}): Promise<{
|
|
1213
|
+
hash: string;
|
|
1214
|
+
blockNumber: number;
|
|
1215
|
+
agentAddress?: string;
|
|
1216
|
+
}>;
|
|
1217
|
+
/**
|
|
1218
|
+
* Revoke the WITHDRAW scope for a position (also zeroes its withdraw floor). Borrower-signed.
|
|
1219
|
+
*
|
|
1220
|
+
* No wallet-type check: revoking is the safe direction, and an EOA that recorded a grant before
|
|
1221
|
+
* this guard existed must be able to clear it.
|
|
1222
|
+
*/
|
|
1223
|
+
disableAutoWithdraw(positionId: string): Promise<{
|
|
1224
|
+
hash: string;
|
|
1225
|
+
blockNumber: number;
|
|
1226
|
+
}>;
|
|
1227
|
+
/**
|
|
1228
|
+
* Layer 2 of the withdrawal-delegation gating: refuse to write a grant that could never be
|
|
1229
|
+
* satisfied. See `enableAutoWithdraw` for why this lives here and not in the registry.
|
|
1230
|
+
*/
|
|
1231
|
+
private assertBorrowerIsContractWallet;
|
|
1232
|
+
/**
|
|
1233
|
+
* Pre-flight the registry's `FloorBelowProtocolMin` guard with a message a user can act on.
|
|
1234
|
+
*
|
|
1235
|
+
* `agentMintFloorMinBps` is the governance floor-of-floors for BOTH the mint and withdraw
|
|
1236
|
+
* grants — one lever, one invariant — so `scope` only shapes the message.
|
|
1237
|
+
*/
|
|
1165
1238
|
private assertMintFloorAtOrAboveProtocolMin;
|
|
1166
1239
|
/**
|
|
1167
1240
|
* Get Bitcoin balance for an address
|
package/dist/safe-delegation.js
CHANGED
|
@@ -326,7 +326,7 @@ var SEPOLIA_DEPLOYMENT = {
|
|
|
326
326
|
CARRY_AGENT_REGISTRY: "0x5595CB538D44E6Cf179D20364fD631D0477e69f7",
|
|
327
327
|
CARRY_AGENT_REGISTRY_IMPL: "0x1b11a3D5e46F3672E643c997f0d569DFf0b64a01",
|
|
328
328
|
AGENT_DELEGATION_REGISTRY: "0x6AE7fc6bE0925126b9D25b1B7Ce5AD5d127ec025",
|
|
329
|
-
AGENT_DELEGATION_REGISTRY_IMPL: "
|
|
329
|
+
AGENT_DELEGATION_REGISTRY_IMPL: "0xE931E4b9ceF2A48Ac7D57192da4B523756cFC310",
|
|
330
330
|
DH_AGENT_DELEGATE: "0xa5A14489ae883960df6E1463A41a47aBE9Ecc5AF"
|
|
331
331
|
}
|
|
332
332
|
};
|
|
@@ -538,7 +538,7 @@ var MAINNET_DEPLOYMENT = {
|
|
|
538
538
|
var LOCALHOST_DEPLOYMENT = {
|
|
539
539
|
network: "localhost",
|
|
540
540
|
chainId: 1337,
|
|
541
|
-
timestamp: "2026-07-
|
|
541
|
+
timestamp: "2026-07-20T19:45:58.514Z",
|
|
542
542
|
deployer: "",
|
|
543
543
|
contracts: {
|
|
544
544
|
MessageHashBuilder: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
|
|
@@ -558,30 +558,6 @@ var LOCALHOST_DEPLOYMENT = {
|
|
|
558
558
|
PositionManager: "0x851356ae760d987E095750cCeb3bC6014560891C",
|
|
559
559
|
OperationAuthorizationRegistry: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
|
|
560
560
|
PKPValidation: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A"
|
|
561
|
-
},
|
|
562
|
-
latestEnv: {
|
|
563
|
-
UCD_TOKEN: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
564
|
-
UCD_CONTROLLER: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
|
|
565
|
-
POSITION_MANAGER: "0x851356ae760d987E095750cCeb3bC6014560891C",
|
|
566
|
-
PKP_VALIDATION_REGISTRY: "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A",
|
|
567
|
-
PKP_VALIDATION_CID_V1: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
|
|
568
|
-
PKP_VALIDATION_CID_V3: "0x12203af2054b0ab6e18d898ddfc7985593439fb82d22336133387c1169f98d3702ab",
|
|
569
|
-
PKP_ETH_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
570
|
-
OPERATION_AUTHORIZATION_REGISTRY: "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75",
|
|
571
|
-
UCD_MINT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
572
|
-
UCD_MINT_VALIDATOR_VERSION: 1,
|
|
573
|
-
BTC_WITHDRAWAL_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
574
|
-
BTC_WITHDRAWAL_VALIDATOR_VERSION: 3,
|
|
575
|
-
UPDATE_BALANCE_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
576
|
-
UPDATE_BALANCE_VALIDATOR_VERSION: 1,
|
|
577
|
-
PROCESS_PAYMENT_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
578
|
-
PROCESS_PAYMENT_VALIDATOR_VERSION: 1,
|
|
579
|
-
EXTEND_POSITION_VALIDATOR_ADDRESS: "0x406f6a9855de2f5577b1525f0600461f02859bd0",
|
|
580
|
-
EXTEND_POSITION_VALIDATOR_VERSION: 1,
|
|
581
|
-
POSITION_MANAGER_CORE_MODULE: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
|
|
582
|
-
LOAN_OPERATIONS_MANAGER_MODULE: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
|
|
583
|
-
TERM_MANAGER_MODULE: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
|
|
584
|
-
COMMUNITY_MANAGER_MODULE: ""
|
|
585
561
|
}
|
|
586
562
|
};
|
|
587
563
|
var ALL_DEPLOYMENTS = {
|