@gvnrdao/dh-sdk 0.0.274 → 0.0.276
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/constants/chunks/deployment-addresses.d.ts +2 -0
- package/dist/constants/chunks/network-configs.d.ts +2 -0
- package/dist/deployments.js +15 -11
- package/dist/deployments.mjs +15 -11
- package/dist/index.d.ts +2 -0
- package/dist/index.js +454 -37
- package/dist/index.mjs +452 -37
- package/dist/interfaces/chunks/config.i.d.ts +2 -0
- package/dist/modules/contract/contract-manager.module.d.ts +7 -1
- package/dist/modules/diamond-hands-sdk.d.ts +59 -0
- package/dist/modules/withdrawal-address/withdrawal-address.module.d.ts +78 -0
- package/dist/utils/address-conversion.utils.d.ts +12 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -3671,7 +3671,8 @@ var init_deployment_addresses = __esm({
|
|
|
3671
3671
|
mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
|
|
3672
3672
|
mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
|
|
3673
3673
|
PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
|
|
3674
|
-
FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
|
|
3674
|
+
FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
|
|
3675
|
+
BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
|
|
3675
3676
|
},
|
|
3676
3677
|
upgraded: {
|
|
3677
3678
|
PositionManager: {
|
|
@@ -3682,11 +3683,11 @@ var init_deployment_addresses = __esm({
|
|
|
3682
3683
|
reason: "Shared upgrade script: PositionManager implementation update"
|
|
3683
3684
|
},
|
|
3684
3685
|
LoanOperationsManagerModule: {
|
|
3685
|
-
previousImplementation: "
|
|
3686
|
-
newImplementation: "
|
|
3687
|
-
upgradedAt: "2026-
|
|
3686
|
+
previousImplementation: "0x9DA8d69d7BcF9Fa3ba5734580e8C32618aB52D36",
|
|
3687
|
+
newImplementation: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
|
|
3688
|
+
upgradedAt: "2026-06-05T10:52:25.179Z",
|
|
3688
3689
|
upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
|
|
3689
|
-
reason: "
|
|
3690
|
+
reason: "audit #3 v1.6.0: LoanOperationsManagerModule \u2014 Chainlink feed-staleness gate (maxBtcFeedAgeBorrow / maxBtcFeedAgeLiquidation)"
|
|
3690
3691
|
},
|
|
3691
3692
|
UCDController: {
|
|
3692
3693
|
previousImplementation: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
|
|
@@ -3745,9 +3746,9 @@ var init_deployment_addresses = __esm({
|
|
|
3745
3746
|
reason: "Shared upgrade script: PositionManagerCoreModule implementation update"
|
|
3746
3747
|
},
|
|
3747
3748
|
CollateralManagerModule: {
|
|
3748
|
-
previousImplementation: "
|
|
3749
|
-
newImplementation: "
|
|
3750
|
-
upgradedAt: "2026-
|
|
3749
|
+
previousImplementation: "0x124e61aBff60CC70c4B81ab3019A8A7D35B412d4",
|
|
3750
|
+
newImplementation: "0xd47FE9126daE9A1e0fFdaCf539BE7345D3642bcb",
|
|
3751
|
+
upgradedAt: "2026-06-05T09:14:12.892Z",
|
|
3751
3752
|
upgradedBy: "0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6",
|
|
3752
3753
|
reason: "Shared upgrade script: CollateralManagerModule implementation update"
|
|
3753
3754
|
},
|
|
@@ -3891,7 +3892,7 @@ var init_deployment_addresses = __esm({
|
|
|
3891
3892
|
CIRCUIT_BREAKER_MODULE: "0x3D0B2cAE481821E57BA9CC3807bCC0d0D7F18bd8",
|
|
3892
3893
|
ADMIN_MODULE: "0xAcd1f07915b17CA3727e7fE89BdF618A1545a1ed",
|
|
3893
3894
|
UCD_CONTROLLER_IMPL: "0x30d0458bE846f4C5D231242eB5a9e9Db68e7232F",
|
|
3894
|
-
LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "
|
|
3895
|
+
LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x8c20e9Edf44146718F2EF15eEF47A201CaC229B8",
|
|
3895
3896
|
TERM_MANAGER_MODULE_IMPL: "0x358d6A7A864853beAA3E157fEB83dCEb1628E8eB",
|
|
3896
3897
|
CIRCUIT_BREAKER_MODULE_IMPL: "0xF6277dEF72D51312CC99616B5380f34Eb7603D75",
|
|
3897
3898
|
ADMIN_MODULE_IMPL: "0xBBA86246169f81a307Fafff02C1e3D8456aab973",
|
|
@@ -3923,7 +3924,9 @@ var init_deployment_addresses = __esm({
|
|
|
3923
3924
|
AGENT_MODULE: "0xefb8C29C1e7e92ed7d81a52dbedaed74e37fe380",
|
|
3924
3925
|
FEE_RECIPIENT_REGISTRY: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
|
|
3925
3926
|
FEE_RECIPIENT_REGISTRY_IMPL: "0xd08513a7cB2dd354B26cDDf549616F12054c34c9",
|
|
3926
|
-
OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D"
|
|
3927
|
+
OPERATION_AUTHORIZATION_REGISTRY_IMPL: "0x9f8072d4672d643e39d8638478e900Fea1f2c81D",
|
|
3928
|
+
BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe",
|
|
3929
|
+
BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_IMPL: "0xFF270BC4470dBA80430Bd1a3a66EB691599354fA"
|
|
3927
3930
|
}
|
|
3928
3931
|
};
|
|
3929
3932
|
SEPOLIA_CONTRACTS = {
|
|
@@ -3950,7 +3953,8 @@ var init_deployment_addresses = __esm({
|
|
|
3950
3953
|
mockUsdcToken: "0x96409A98e0D322d6566b7F44a0fAbD1BD4ce2AEc",
|
|
3951
3954
|
mockUsdtToken: "0xF8b7fB38b17a310960E47805Be9adba0b0e0394D",
|
|
3952
3955
|
PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9",
|
|
3953
|
-
FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374"
|
|
3956
|
+
FeeRecipientRegistry: "0x95795F8403DDb629E8527B2934C4e71f5fC0C374",
|
|
3957
|
+
BitcoinWithdrawalAddressRegistry: "0x6376D392097F0A81e51BD83960A97EA20eaf1dbe"
|
|
3954
3958
|
};
|
|
3955
3959
|
LOCALHOST_DEPLOYMENT = {
|
|
3956
3960
|
network: "localhost",
|
|
@@ -7266,7 +7270,7 @@ var require_abstract_coder = __commonJS({
|
|
|
7266
7270
|
function toObject2(names2, items, deep) {
|
|
7267
7271
|
if (names2.indexOf(null) >= 0) {
|
|
7268
7272
|
return items.map((item, index) => {
|
|
7269
|
-
if (item instanceof
|
|
7273
|
+
if (item instanceof Result11) {
|
|
7270
7274
|
return toObject2(getNames2(item), item, deep);
|
|
7271
7275
|
}
|
|
7272
7276
|
return item;
|
|
@@ -7275,7 +7279,7 @@ var require_abstract_coder = __commonJS({
|
|
|
7275
7279
|
return names2.reduce((accum, name, index) => {
|
|
7276
7280
|
let item = items.getValue(name);
|
|
7277
7281
|
if (!(name in accum)) {
|
|
7278
|
-
if (deep && item instanceof
|
|
7282
|
+
if (deep && item instanceof Result11) {
|
|
7279
7283
|
item = toObject2(getNames2(item), item, deep);
|
|
7280
7284
|
}
|
|
7281
7285
|
accum[name] = item;
|
|
@@ -7283,7 +7287,7 @@ var require_abstract_coder = __commonJS({
|
|
|
7283
7287
|
return accum;
|
|
7284
7288
|
}, {});
|
|
7285
7289
|
}
|
|
7286
|
-
var
|
|
7290
|
+
var Result11 = class _Result extends Array {
|
|
7287
7291
|
// No longer used; but cannot be removed as it will remove the
|
|
7288
7292
|
// #private field from the .d.ts which may break backwards
|
|
7289
7293
|
// compatibility
|
|
@@ -7487,7 +7491,7 @@ var require_abstract_coder = __commonJS({
|
|
|
7487
7491
|
return new _Result(_guard5, items, keys);
|
|
7488
7492
|
}
|
|
7489
7493
|
};
|
|
7490
|
-
exports2.Result =
|
|
7494
|
+
exports2.Result = Result11;
|
|
7491
7495
|
function checkResultErrors2(result) {
|
|
7492
7496
|
const errors2 = [];
|
|
7493
7497
|
const checkErrors = function(path2, object2) {
|
|
@@ -20178,9 +20182,9 @@ var require_contract = __commonJS({
|
|
|
20178
20182
|
function _ContractBase2() {
|
|
20179
20183
|
return BaseContract2;
|
|
20180
20184
|
}
|
|
20181
|
-
var
|
|
20185
|
+
var Contract3 = class extends _ContractBase2() {
|
|
20182
20186
|
};
|
|
20183
|
-
exports2.Contract =
|
|
20187
|
+
exports2.Contract = Contract3;
|
|
20184
20188
|
}
|
|
20185
20189
|
});
|
|
20186
20190
|
|
|
@@ -31445,17 +31449,17 @@ var require_pkg_src = __commonJS({
|
|
|
31445
31449
|
}
|
|
31446
31450
|
},
|
|
31447
31451
|
btcWithdrawal: {
|
|
31448
|
-
cid: "
|
|
31452
|
+
cid: "QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp",
|
|
31449
31453
|
authorizedCidHex: cidToHex(
|
|
31450
|
-
"
|
|
31454
|
+
"QmNqErzpgDUair9bPK7oPQczjKjRcsmcej37izponrEcqp"
|
|
31451
31455
|
),
|
|
31452
31456
|
name: "Btc Withdrawal",
|
|
31453
31457
|
description: "Production Btc Withdrawal",
|
|
31454
31458
|
version: "1.0.0",
|
|
31455
31459
|
deployed: true,
|
|
31456
|
-
deployedAt:
|
|
31457
|
-
size:
|
|
31458
|
-
hash: "
|
|
31460
|
+
deployedAt: 1780651980768,
|
|
31461
|
+
size: 75137,
|
|
31462
|
+
hash: "368f9aea32cf2e660b0f75b88b6ee043cf5956319d7b3c6c695d4b984b3bd555",
|
|
31459
31463
|
validatorWalletAddress: "0xbb137fbda353199e9419b698c57a742124d4987d",
|
|
31460
31464
|
pkp: {
|
|
31461
31465
|
publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
|
|
@@ -32328,7 +32332,7 @@ ${errorReport}`);
|
|
|
32328
32332
|
}
|
|
32329
32333
|
init_debug_logger();
|
|
32330
32334
|
init_session_signature_cache();
|
|
32331
|
-
var
|
|
32335
|
+
var import_ethers14 = require_lib2();
|
|
32332
32336
|
var EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS = 11e3;
|
|
32333
32337
|
var GRACE_PERIOD_DAYS = 30;
|
|
32334
32338
|
var SATOSHIS_PER_BITCOIN = 100000000n;
|
|
@@ -34480,12 +34484,12 @@ ${errorReport}`);
|
|
|
34480
34484
|
}
|
|
34481
34485
|
async function executeVaultSnapshot(params) {
|
|
34482
34486
|
global.ethers = {
|
|
34483
|
-
...
|
|
34487
|
+
...import_ethers14.ethers,
|
|
34484
34488
|
providers: {
|
|
34485
|
-
StaticJsonRpcProvider:
|
|
34489
|
+
StaticJsonRpcProvider: import_ethers14.ethers.JsonRpcProvider
|
|
34486
34490
|
},
|
|
34487
|
-
Contract:
|
|
34488
|
-
utils:
|
|
34491
|
+
Contract: import_ethers14.ethers.Contract,
|
|
34492
|
+
utils: import_ethers14.ethers
|
|
34489
34493
|
// v6 moved utils to top level
|
|
34490
34494
|
};
|
|
34491
34495
|
global.Lit = {
|
|
@@ -34753,7 +34757,8 @@ function getSepoliaConfig() {
|
|
|
34753
34757
|
bitcoinProviderRegistry: SEPOLIA_CONTRACTS.BitcoinProviderRegistry || "",
|
|
34754
34758
|
contractVersionRegistry: SEPOLIA_CONTRACTS.ContractVersionRegistry || "",
|
|
34755
34759
|
feeRecipientRegistry: SEPOLIA_CONTRACTS.FeeRecipientRegistry || "",
|
|
34756
|
-
positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || ""
|
|
34760
|
+
positionDelegateRegistry: SEPOLIA_CONTRACTS.PositionDelegateRegistry || "",
|
|
34761
|
+
bitcoinWithdrawalAddressRegistry: SEPOLIA_CONTRACTS.BitcoinWithdrawalAddressRegistry || ""
|
|
34757
34762
|
},
|
|
34758
34763
|
subgraphs: {
|
|
34759
34764
|
// Lazy getter for the same module-init snapshot reason as serviceEndpoint.
|
|
@@ -37197,9 +37202,9 @@ var require_ToPrimitive = __commonJS({
|
|
|
37197
37202
|
}
|
|
37198
37203
|
});
|
|
37199
37204
|
|
|
37200
|
-
// node_modules/es-abstract/
|
|
37205
|
+
// node_modules/es-abstract/2025/ToString.js
|
|
37201
37206
|
var require_ToString = __commonJS({
|
|
37202
|
-
"node_modules/es-abstract/
|
|
37207
|
+
"node_modules/es-abstract/2025/ToString.js"(exports2, module2) {
|
|
37203
37208
|
"use strict";
|
|
37204
37209
|
var GetIntrinsic = require_get_intrinsic();
|
|
37205
37210
|
var $String = GetIntrinsic("%String%");
|
|
@@ -37220,13 +37225,20 @@ var require_implementation3 = __commonJS({
|
|
|
37220
37225
|
var RequireObjectCoercible = require_RequireObjectCoercible();
|
|
37221
37226
|
var ToString = require_ToString();
|
|
37222
37227
|
var callBound = require_call_bound();
|
|
37228
|
+
var safeRegexTester = require_safe_regex_test();
|
|
37223
37229
|
var $replace = callBound("String.prototype.replace");
|
|
37230
|
+
var $charAt = callBound("String.prototype.charAt");
|
|
37231
|
+
var $slice = callBound("String.prototype.slice");
|
|
37224
37232
|
var mvsIsWS = /^\s$/.test("\u180E");
|
|
37225
37233
|
var leftWhitespace = mvsIsWS ? /^[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+/ : /^[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]+/;
|
|
37226
|
-
var
|
|
37234
|
+
var isWhitespace = safeRegexTester(mvsIsWS ? /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]$/ : /[\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]$/);
|
|
37227
37235
|
module2.exports = function trim() {
|
|
37228
|
-
var S = ToString(RequireObjectCoercible(this));
|
|
37229
|
-
|
|
37236
|
+
var S = $replace(ToString(RequireObjectCoercible(this)), leftWhitespace, "");
|
|
37237
|
+
var end = S.length;
|
|
37238
|
+
while (end > 0 && isWhitespace($charAt(S, end - 1))) {
|
|
37239
|
+
end -= 1;
|
|
37240
|
+
}
|
|
37241
|
+
return $slice(S, 0, end);
|
|
37230
37242
|
};
|
|
37231
37243
|
}
|
|
37232
37244
|
});
|
|
@@ -37479,6 +37491,22 @@ var require_ToObject = __commonJS({
|
|
|
37479
37491
|
}
|
|
37480
37492
|
});
|
|
37481
37493
|
|
|
37494
|
+
// node_modules/es-abstract/2024/ToString.js
|
|
37495
|
+
var require_ToString2 = __commonJS({
|
|
37496
|
+
"node_modules/es-abstract/2024/ToString.js"(exports2, module2) {
|
|
37497
|
+
"use strict";
|
|
37498
|
+
var GetIntrinsic = require_get_intrinsic();
|
|
37499
|
+
var $String = GetIntrinsic("%String%");
|
|
37500
|
+
var $TypeError = require_type();
|
|
37501
|
+
module2.exports = function ToString(argument) {
|
|
37502
|
+
if (typeof argument === "symbol") {
|
|
37503
|
+
throw new $TypeError("Cannot convert a Symbol value to a string");
|
|
37504
|
+
}
|
|
37505
|
+
return $String(argument);
|
|
37506
|
+
};
|
|
37507
|
+
}
|
|
37508
|
+
});
|
|
37509
|
+
|
|
37482
37510
|
// node_modules/array.prototype.findindex/implementation.js
|
|
37483
37511
|
var require_implementation4 = __commonJS({
|
|
37484
37512
|
"node_modules/array.prototype.findindex/implementation.js"(exports2, module2) {
|
|
@@ -37489,7 +37517,7 @@ var require_implementation4 = __commonJS({
|
|
|
37489
37517
|
var LengthOfArrayLike = require_LengthOfArrayLike();
|
|
37490
37518
|
var ToBoolean = require_ToBoolean();
|
|
37491
37519
|
var ToObject = require_ToObject();
|
|
37492
|
-
var ToString =
|
|
37520
|
+
var ToString = require_ToString2();
|
|
37493
37521
|
module2.exports = function findIndex(predicate) {
|
|
37494
37522
|
var O = ToObject(this);
|
|
37495
37523
|
var len = LengthOfArrayLike(O);
|
|
@@ -90082,6 +90110,7 @@ __export(src_exports, {
|
|
|
90082
90110
|
UCDConversions: () => UCDConversions,
|
|
90083
90111
|
VALID_LIT_NETWORKS: () => VALID_LIT_NETWORKS,
|
|
90084
90112
|
WeiConversions: () => WeiConversions,
|
|
90113
|
+
WithdrawalAddressModule: () => WithdrawalAddressModule,
|
|
90085
90114
|
andThen: () => andThen,
|
|
90086
90115
|
assertProtocolNotPaused: () => assertProtocolNotPaused,
|
|
90087
90116
|
assertSafeServiceEndpoint: () => assertSafeServiceEndpoint,
|
|
@@ -90096,6 +90125,7 @@ __export(src_exports, {
|
|
|
90096
90125
|
createLoanQuery: () => createLoanQuery,
|
|
90097
90126
|
createMockTokenManager: () => createMockTokenManager,
|
|
90098
90127
|
createPKPManager: () => createPKPManager,
|
|
90128
|
+
createWithdrawalAddressModule: () => createWithdrawalAddressModule,
|
|
90099
90129
|
default: () => DiamondHandsSDK,
|
|
90100
90130
|
failure: () => failure,
|
|
90101
90131
|
fetchProtocolPauseStatus: () => fetchProtocolPauseStatus,
|
|
@@ -94331,6 +94361,13 @@ var ZeroAddress = "0x0000000000000000000000000000000000000000";
|
|
|
94331
94361
|
// node_modules/ethers/lib.esm/constants/hashes.js
|
|
94332
94362
|
var ZeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
94333
94363
|
|
|
94364
|
+
// node_modules/ethers/lib.esm/constants/numbers.js
|
|
94365
|
+
var N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
|
94366
|
+
var WeiPerEther = BigInt("1000000000000000000");
|
|
94367
|
+
var MaxUint256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
94368
|
+
var MinInt256 = BigInt("0x8000000000000000000000000000000000000000000000000000000000000000") * BigInt(-1);
|
|
94369
|
+
var MaxInt256 = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
94370
|
+
|
|
94334
94371
|
// node_modules/ethers/lib.esm/crypto/signature.js
|
|
94335
94372
|
var BN_04 = BigInt(0);
|
|
94336
94373
|
var BN_13 = BigInt(1);
|
|
@@ -108864,6 +108901,15 @@ function safeValidateBitcoinAddress(address, network = "regtest") {
|
|
|
108864
108901
|
}
|
|
108865
108902
|
return address;
|
|
108866
108903
|
}
|
|
108904
|
+
function normalizeBitcoinAddress(address) {
|
|
108905
|
+
if (!address || typeof address !== "string")
|
|
108906
|
+
return address;
|
|
108907
|
+
const trimmed = address.trim();
|
|
108908
|
+
if (/^(bc1|tb1|bcrt1)/i.test(trimmed)) {
|
|
108909
|
+
return trimmed.toLowerCase();
|
|
108910
|
+
}
|
|
108911
|
+
return trimmed;
|
|
108912
|
+
}
|
|
108867
108913
|
|
|
108868
108914
|
// src/protocol/protocol-pause.ts
|
|
108869
108915
|
var GET_PROTOCOL_PAUSE_STATUS_ABI = [
|
|
@@ -109055,6 +109101,21 @@ var LIQUIDATION_MANAGER_ABI = [
|
|
|
109055
109101
|
"function canLiquidate(bytes32 positionId) external view returns (bool)",
|
|
109056
109102
|
"function vrfSeeds(bytes32 positionId) external view returns (uint256)"
|
|
109057
109103
|
];
|
|
109104
|
+
var BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI = [
|
|
109105
|
+
"function addAddress(string btcAddress) external",
|
|
109106
|
+
"function removeAddress(string btcAddress) external",
|
|
109107
|
+
"function removeAddressByHash(bytes32 addrHash) external",
|
|
109108
|
+
"function isApproved(address user, string btcAddress) external view returns (bool)",
|
|
109109
|
+
"function isApprovedByHash(address user, bytes32 addrHash) external view returns (bool)",
|
|
109110
|
+
"function isPresent(address user, bytes32 addrHash) external view returns (bool)",
|
|
109111
|
+
"function getAddedAt(address user, bytes32 addrHash) external view returns (uint64)",
|
|
109112
|
+
"function getUsableAt(address user, bytes32 addrHash) external view returns (uint256)",
|
|
109113
|
+
"function getAddressHashes(address user) external view returns (bytes32[])",
|
|
109114
|
+
"function addressCount(address user) external view returns (uint256)",
|
|
109115
|
+
"function addressDelay() external view returns (uint256)",
|
|
109116
|
+
"event AddressAdded(address indexed user, bytes32 indexed addrHash, string btcAddress, uint64 addedAt, uint256 usableAt)",
|
|
109117
|
+
"event AddressRemoved(address indexed user, bytes32 indexed addrHash, string btcAddress)"
|
|
109118
|
+
];
|
|
109058
109119
|
var ContractManager = class {
|
|
109059
109120
|
config;
|
|
109060
109121
|
contracts = null;
|
|
@@ -109115,6 +109176,11 @@ var ContractManager = class {
|
|
|
109115
109176
|
contractAddresses.liquidationManager || ZeroAddress,
|
|
109116
109177
|
LIQUIDATION_MANAGER_ABI,
|
|
109117
109178
|
contractRunner
|
|
109179
|
+
),
|
|
109180
|
+
bitcoinWithdrawalAddressRegistry: new Contract(
|
|
109181
|
+
contractAddresses.bitcoinWithdrawalAddressRegistry || ZeroAddress,
|
|
109182
|
+
BITCOIN_WITHDRAWAL_ADDRESS_REGISTRY_ABI,
|
|
109183
|
+
contractRunner
|
|
109118
109184
|
)
|
|
109119
109185
|
};
|
|
109120
109186
|
this.contracts = contracts;
|
|
@@ -109145,7 +109211,16 @@ var ContractManager = class {
|
|
|
109145
109211
|
"loanOperationsManager",
|
|
109146
109212
|
"termManager",
|
|
109147
109213
|
"circuitBreaker",
|
|
109148
|
-
"liquidationManager"
|
|
109214
|
+
"liquidationManager",
|
|
109215
|
+
// INTENTIONALLY OPTIONAL — do not promote to requiredAddresses.
|
|
109216
|
+
// The on-chain CollateralManager gate is inert while its registry is
|
|
109217
|
+
// address(0) (staged rollout), so pre-v1.3 deployments, browser/default
|
|
109218
|
+
// configs, and tests legitimately omit this address. The SDK's layer-1
|
|
109219
|
+
// early-reject (WithdrawalAddressModule.assertApprovedForWithdrawal)
|
|
109220
|
+
// already no-ops via isConfigured() when the address is absent/ZeroAddress,
|
|
109221
|
+
// and the contract instance defaults to ZeroAddress. Making this required
|
|
109222
|
+
// would throw at init for every config that hasn't deployed the registry.
|
|
109223
|
+
"bitcoinWithdrawalAddressRegistry"
|
|
109149
109224
|
];
|
|
109150
109225
|
const missing = [];
|
|
109151
109226
|
const invalid = [];
|
|
@@ -109258,6 +109333,16 @@ var ContractManager = class {
|
|
|
109258
109333
|
}
|
|
109259
109334
|
return success(contractsResult.value.liquidationManager);
|
|
109260
109335
|
}
|
|
109336
|
+
/**
|
|
109337
|
+
* Get the BitcoinWithdrawalAddressRegistry contract (per-wallet approved-address allowlist).
|
|
109338
|
+
*/
|
|
109339
|
+
getBitcoinWithdrawalAddressRegistry() {
|
|
109340
|
+
const contractsResult = this.getContracts();
|
|
109341
|
+
if (!contractsResult.success) {
|
|
109342
|
+
return contractsResult;
|
|
109343
|
+
}
|
|
109344
|
+
return success(contractsResult.value.bitcoinWithdrawalAddressRegistry);
|
|
109345
|
+
}
|
|
109261
109346
|
/**
|
|
109262
109347
|
* Get the provider instance
|
|
109263
109348
|
*/
|
|
@@ -111347,6 +111432,168 @@ function createLoanQuery(config) {
|
|
|
111347
111432
|
}
|
|
111348
111433
|
}
|
|
111349
111434
|
|
|
111435
|
+
// src/modules/withdrawal-address/withdrawal-address.module.ts
|
|
111436
|
+
var WithdrawalAddressModule = class {
|
|
111437
|
+
config;
|
|
111438
|
+
constructor(config) {
|
|
111439
|
+
this.config = config;
|
|
111440
|
+
}
|
|
111441
|
+
/** Resolve the registry contract, or fail if it isn't configured for this network. */
|
|
111442
|
+
getRegistry() {
|
|
111443
|
+
const res = this.config.contractManager.getBitcoinWithdrawalAddressRegistry();
|
|
111444
|
+
if (!res.success)
|
|
111445
|
+
return res;
|
|
111446
|
+
const target = res.value.target;
|
|
111447
|
+
if (!target || target === ZeroAddress) {
|
|
111448
|
+
return failure(
|
|
111449
|
+
new SDKError({
|
|
111450
|
+
code: "SDK_WITHDRAWAL_REGISTRY_NOT_CONFIGURED",
|
|
111451
|
+
message: "BitcoinWithdrawalAddressRegistry address is not configured for this network",
|
|
111452
|
+
category: "CONFIGURATION" /* CONFIGURATION */,
|
|
111453
|
+
severity: "MEDIUM" /* MEDIUM */
|
|
111454
|
+
})
|
|
111455
|
+
);
|
|
111456
|
+
}
|
|
111457
|
+
return success(res.value);
|
|
111458
|
+
}
|
|
111459
|
+
/** True iff the registry is wired for this network (enforcement is active). */
|
|
111460
|
+
isConfigured() {
|
|
111461
|
+
return this.getRegistry().success;
|
|
111462
|
+
}
|
|
111463
|
+
/** keccak256 of the canonicalized address — matches the on-chain key. */
|
|
111464
|
+
static addressHash(btcAddress) {
|
|
111465
|
+
return keccak256(toUtf8Bytes(normalizeBitcoinAddress(btcAddress)));
|
|
111466
|
+
}
|
|
111467
|
+
/**
|
|
111468
|
+
* Add a Bitcoin address to the caller's allowlist. It becomes usable only
|
|
111469
|
+
* after the registry's delay elapses. Returns the submitted tx.
|
|
111470
|
+
*/
|
|
111471
|
+
async addAddress(btcAddress) {
|
|
111472
|
+
const reg = this.getRegistry();
|
|
111473
|
+
if (!reg.success)
|
|
111474
|
+
return reg;
|
|
111475
|
+
try {
|
|
111476
|
+
const tx = await reg.value.addAddress(
|
|
111477
|
+
normalizeBitcoinAddress(btcAddress)
|
|
111478
|
+
);
|
|
111479
|
+
return success(tx);
|
|
111480
|
+
} catch (error2) {
|
|
111481
|
+
return this.txFailure("addAddress", error2, btcAddress);
|
|
111482
|
+
}
|
|
111483
|
+
}
|
|
111484
|
+
/** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
|
|
111485
|
+
async removeAddress(btcAddress) {
|
|
111486
|
+
const reg = this.getRegistry();
|
|
111487
|
+
if (!reg.success)
|
|
111488
|
+
return reg;
|
|
111489
|
+
try {
|
|
111490
|
+
const tx = await reg.value.removeAddress(
|
|
111491
|
+
normalizeBitcoinAddress(btcAddress)
|
|
111492
|
+
);
|
|
111493
|
+
return success(tx);
|
|
111494
|
+
} catch (error2) {
|
|
111495
|
+
return this.txFailure("removeAddress", error2, btcAddress);
|
|
111496
|
+
}
|
|
111497
|
+
}
|
|
111498
|
+
/**
|
|
111499
|
+
* Authoritative contract read: is `btcAddress` approved (present AND past its
|
|
111500
|
+
* delay) for `user`?
|
|
111501
|
+
*/
|
|
111502
|
+
async isApproved(user, btcAddress) {
|
|
111503
|
+
const reg = this.getRegistry();
|
|
111504
|
+
if (!reg.success)
|
|
111505
|
+
return reg;
|
|
111506
|
+
try {
|
|
111507
|
+
const ok = await reg.value.isApproved(
|
|
111508
|
+
user,
|
|
111509
|
+
normalizeBitcoinAddress(btcAddress)
|
|
111510
|
+
);
|
|
111511
|
+
return success(ok);
|
|
111512
|
+
} catch (error2) {
|
|
111513
|
+
return this.txFailure("isApproved", error2, btcAddress);
|
|
111514
|
+
}
|
|
111515
|
+
}
|
|
111516
|
+
/**
|
|
111517
|
+
* Read the user's allowlist from the contract: hashes + timestamps + derived
|
|
111518
|
+
* approval state. NOTE: the raw address strings are NOT on-chain — use the
|
|
111519
|
+
* subgraph (WithdrawalAddressBook) to render human-readable addresses.
|
|
111520
|
+
*/
|
|
111521
|
+
async getEntries(user) {
|
|
111522
|
+
const reg = this.getRegistry();
|
|
111523
|
+
if (!reg.success)
|
|
111524
|
+
return reg;
|
|
111525
|
+
try {
|
|
111526
|
+
const hashes = await reg.value.getAddressHashes(user);
|
|
111527
|
+
const entries = [];
|
|
111528
|
+
for (const addrHash of hashes) {
|
|
111529
|
+
const addedAt = Number(await reg.value.getAddedAt(user, addrHash));
|
|
111530
|
+
const usableAt = Number(await reg.value.getUsableAt(user, addrHash));
|
|
111531
|
+
const approved = await reg.value.isApprovedByHash(
|
|
111532
|
+
user,
|
|
111533
|
+
addrHash
|
|
111534
|
+
);
|
|
111535
|
+
entries.push({ addrHash, addedAt, usableAt, approved });
|
|
111536
|
+
}
|
|
111537
|
+
return success(entries);
|
|
111538
|
+
} catch (error2) {
|
|
111539
|
+
return this.txFailure("getEntries", error2, user);
|
|
111540
|
+
}
|
|
111541
|
+
}
|
|
111542
|
+
/** The current global delay (seconds) before a newly-added address is usable. */
|
|
111543
|
+
async getAddressDelay() {
|
|
111544
|
+
const reg = this.getRegistry();
|
|
111545
|
+
if (!reg.success)
|
|
111546
|
+
return reg;
|
|
111547
|
+
try {
|
|
111548
|
+
const delay = await reg.value.addressDelay();
|
|
111549
|
+
return success(Number(delay));
|
|
111550
|
+
} catch (error2) {
|
|
111551
|
+
return this.txFailure("addressDelay", error2, "");
|
|
111552
|
+
}
|
|
111553
|
+
}
|
|
111554
|
+
/**
|
|
111555
|
+
* Early-reject guard used by `withdrawBTC`. Resolves to a typed error if the
|
|
111556
|
+
* destination is not approved for `borrower`. When the registry is not
|
|
111557
|
+
* configured for the network, this is a no-op (the on-chain gate remains the
|
|
111558
|
+
* hard guarantee).
|
|
111559
|
+
*/
|
|
111560
|
+
async assertApprovedForWithdrawal(borrower, btcAddress) {
|
|
111561
|
+
if (!this.isConfigured())
|
|
111562
|
+
return success(void 0);
|
|
111563
|
+
const res = await this.isApproved(borrower, btcAddress);
|
|
111564
|
+
if (!res.success)
|
|
111565
|
+
return res;
|
|
111566
|
+
if (!res.value) {
|
|
111567
|
+
return failure(
|
|
111568
|
+
new SDKError({
|
|
111569
|
+
code: "SDK_WITHDRAWAL_ADDRESS_NOT_APPROVED",
|
|
111570
|
+
message: `Bitcoin address ${btcAddress} is not an approved withdrawal destination for ${borrower} (not on the allowlist, or its time-lock has not elapsed). Add it and wait for the delay first.`,
|
|
111571
|
+
category: "VALIDATION" /* VALIDATION */,
|
|
111572
|
+
severity: "MEDIUM" /* MEDIUM */,
|
|
111573
|
+
context: { borrower, btcAddress }
|
|
111574
|
+
})
|
|
111575
|
+
);
|
|
111576
|
+
}
|
|
111577
|
+
return success(void 0);
|
|
111578
|
+
}
|
|
111579
|
+
txFailure(op, error2, context) {
|
|
111580
|
+
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
111581
|
+
return failure(
|
|
111582
|
+
new SDKError({
|
|
111583
|
+
code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
|
|
111584
|
+
message: `WithdrawalAddressRegistry.${op} failed: ${msg}`,
|
|
111585
|
+
category: "CONTRACT" /* CONTRACT */,
|
|
111586
|
+
severity: "MEDIUM" /* MEDIUM */,
|
|
111587
|
+
originalError: error2 instanceof Error ? error2 : new Error(String(error2)),
|
|
111588
|
+
context: { op, context }
|
|
111589
|
+
})
|
|
111590
|
+
);
|
|
111591
|
+
}
|
|
111592
|
+
};
|
|
111593
|
+
function createWithdrawalAddressModule(config) {
|
|
111594
|
+
return new WithdrawalAddressModule(config);
|
|
111595
|
+
}
|
|
111596
|
+
|
|
111350
111597
|
// src/types/branded/domain-values.ts
|
|
111351
111598
|
var UCD_BRAND = Symbol.for("diamond-hands.UCD");
|
|
111352
111599
|
var SATOSHIS_BRAND = Symbol.for("diamond-hands.Satoshis");
|
|
@@ -117179,6 +117426,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
117179
117426
|
loanCreator;
|
|
117180
117427
|
loanQuery;
|
|
117181
117428
|
bitcoinOperations;
|
|
117429
|
+
withdrawalAddressModule;
|
|
117182
117430
|
mockTokenManager;
|
|
117183
117431
|
graphClient;
|
|
117184
117432
|
/**
|
|
@@ -117362,6 +117610,10 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
117362
117610
|
);
|
|
117363
117611
|
}
|
|
117364
117612
|
this.contractManager = contractManagerResult.value;
|
|
117613
|
+
this.withdrawalAddressModule = createWithdrawalAddressModule({
|
|
117614
|
+
contractManager: this.contractManager,
|
|
117615
|
+
debug: config.debug
|
|
117616
|
+
});
|
|
117365
117617
|
this.litOps = new import_dh_lit_ops.LitOps({
|
|
117366
117618
|
mode: config.mode || "standalone",
|
|
117367
117619
|
network: config.litNetwork || DEFAULT_LIT_NETWORK,
|
|
@@ -117436,6 +117688,11 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
117436
117688
|
);
|
|
117437
117689
|
}
|
|
117438
117690
|
const graphHeaders = !serviceMode && config.graphApiKey ? { Authorization: `Bearer ${config.graphApiKey}` } : void 0;
|
|
117691
|
+
if (graphHeaders && typeof window !== "undefined" && typeof window.document !== "undefined") {
|
|
117692
|
+
log.warn(
|
|
117693
|
+
"graphApiKey is being used in standalone mode inside a browser \u2014 the key will be exposed to end users. Use service mode (serviceEndpoint + session auth) for any user-facing app so GRAPH_API_KEY stays server-side."
|
|
117694
|
+
);
|
|
117695
|
+
}
|
|
117439
117696
|
this.graphClient = new DiamondHandsGraph(
|
|
117440
117697
|
{
|
|
117441
117698
|
endpoint: graphEndpoint,
|
|
@@ -118247,7 +118504,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118247
118504
|
);
|
|
118248
118505
|
}
|
|
118249
118506
|
const chain = this.config.chain || (Number(network2.chainId) === 1 ? "ethereum" : "sepolia");
|
|
118250
|
-
const devBitcoinProviderUrl =
|
|
118507
|
+
const devBitcoinProviderUrl = request.customBitcoinRpcUrl || this.config.bitcoinProviders?.[0]?.url;
|
|
118251
118508
|
if (this.config.debug) {
|
|
118252
118509
|
log.info(` Network: ${chain} (chainId: ${network2.chainId})`);
|
|
118253
118510
|
}
|
|
@@ -118293,7 +118550,17 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118293
118550
|
contractAddresses: contracts
|
|
118294
118551
|
},
|
|
118295
118552
|
userSignature: auth.signature,
|
|
118296
|
-
|
|
118553
|
+
// lit-ops reads `bitcoinProviderUrl` (request field) and maps it to the
|
|
118554
|
+
// validator's `devBitcoinProviderUrl` jsParam on Hardhat.
|
|
118555
|
+
...devBitcoinProviderUrl ? { bitcoinProviderUrl: devBitcoinProviderUrl } : {},
|
|
118556
|
+
// Optional override of the mint validator PKP/wallet (e.g. an on-chain-multisig-authorized
|
|
118557
|
+
// validator) — applied to a local copy in lit-ops, never mutating the registry singleton.
|
|
118558
|
+
// When set, authorization is by the on-chain ACTION CID, so the posted code must stay
|
|
118559
|
+
// byte-identical to the registry code (no cache-bust nonce) or the derived CID won't match.
|
|
118560
|
+
...this.config.mintValidatorOverride ? {
|
|
118561
|
+
validatorOverride: this.config.mintValidatorOverride,
|
|
118562
|
+
disableCacheBust: true
|
|
118563
|
+
} : {},
|
|
118297
118564
|
rpcUrl: request.rpcUrl || this.config.ethRpcUrl,
|
|
118298
118565
|
// Pass RPC URL to LIT Action (ngrok for Hardhat)
|
|
118299
118566
|
...request.debugOverrides && {
|
|
@@ -121309,6 +121576,40 @@ Error data: ${errorData || "none"}`
|
|
|
121309
121576
|
this.releaseWriteLock(request.positionId);
|
|
121310
121577
|
}
|
|
121311
121578
|
}
|
|
121579
|
+
/**
|
|
121580
|
+
* Access the approved-withdrawal-address allowlist module (self-service
|
|
121581
|
+
* add/remove + reads). The connected wallet manages its OWN addresses; a
|
|
121582
|
+
* newly-added address is only usable after the registry's time-lock delay.
|
|
121583
|
+
*/
|
|
121584
|
+
get withdrawalAddresses() {
|
|
121585
|
+
return this.withdrawalAddressModule;
|
|
121586
|
+
}
|
|
121587
|
+
/**
|
|
121588
|
+
* Add a Bitcoin address to the connected wallet's approved-withdrawal allowlist.
|
|
121589
|
+
* Usable only after the registry's delay (default 24h) elapses.
|
|
121590
|
+
*/
|
|
121591
|
+
async addApprovedWithdrawalAddress(btcAddress) {
|
|
121592
|
+
return this.withdrawalAddressModule.addAddress(btcAddress);
|
|
121593
|
+
}
|
|
121594
|
+
/** Remove a Bitcoin address from the connected wallet's allowlist (immediate). */
|
|
121595
|
+
async removeApprovedWithdrawalAddress(btcAddress) {
|
|
121596
|
+
return this.withdrawalAddressModule.removeAddress(btcAddress);
|
|
121597
|
+
}
|
|
121598
|
+
/**
|
|
121599
|
+
* Read the connected wallet's (or `user`'s) approved-address entries from the
|
|
121600
|
+
* contract (hashes + timestamps + derived approval state). For human-readable
|
|
121601
|
+
* address strings, query the subgraph `WithdrawalAddressBook`.
|
|
121602
|
+
*/
|
|
121603
|
+
async getApprovedWithdrawalAddresses(user) {
|
|
121604
|
+
let target = user;
|
|
121605
|
+
if (!target) {
|
|
121606
|
+
const signerRes = this.contractManager.getSigner();
|
|
121607
|
+
if (!signerRes.success)
|
|
121608
|
+
return signerRes;
|
|
121609
|
+
target = await signerRes.value.getAddress();
|
|
121610
|
+
}
|
|
121611
|
+
return this.withdrawalAddressModule.getEntries(target);
|
|
121612
|
+
}
|
|
121312
121613
|
/**
|
|
121313
121614
|
* Withdraw Bitcoin from a position
|
|
121314
121615
|
*
|
|
@@ -121393,6 +121694,48 @@ Error data: ${errorData || "none"}`
|
|
|
121393
121694
|
if (this.config.debug) {
|
|
121394
121695
|
log.info(` Position PKP ID: ${position.pkpId}`);
|
|
121395
121696
|
}
|
|
121697
|
+
if (this.withdrawalAddressModule.isConfigured()) {
|
|
121698
|
+
const rawStatus = position.status;
|
|
121699
|
+
const isLiquidated = Number(rawStatus) === 5 || String(rawStatus).toUpperCase() === "LIQUIDATED";
|
|
121700
|
+
let controller;
|
|
121701
|
+
if (isLiquidated) {
|
|
121702
|
+
const litValidatorAddr = this.getContractAddressesOrThrow().litActionValidator;
|
|
121703
|
+
const pkpId = position.pkpId;
|
|
121704
|
+
if (litValidatorAddr && pkpId) {
|
|
121705
|
+
try {
|
|
121706
|
+
const litValidator = new Contract(
|
|
121707
|
+
litValidatorAddr,
|
|
121708
|
+
["function pkpOwners(bytes32) view returns (address)"],
|
|
121709
|
+
this.getProviderOrThrow()
|
|
121710
|
+
);
|
|
121711
|
+
const owner = await litValidator.pkpOwners(
|
|
121712
|
+
pkpId
|
|
121713
|
+
);
|
|
121714
|
+
if (owner && owner !== ZeroAddress) {
|
|
121715
|
+
controller = owner;
|
|
121716
|
+
}
|
|
121717
|
+
} catch {
|
|
121718
|
+
}
|
|
121719
|
+
}
|
|
121720
|
+
} else {
|
|
121721
|
+
controller = position.borrower;
|
|
121722
|
+
if (!controller) {
|
|
121723
|
+
const signerRes = this.contractManager.getSigner();
|
|
121724
|
+
if (signerRes.success) {
|
|
121725
|
+
controller = await signerRes.value.getAddress();
|
|
121726
|
+
}
|
|
121727
|
+
}
|
|
121728
|
+
}
|
|
121729
|
+
if (controller) {
|
|
121730
|
+
const approval = await this.withdrawalAddressModule.assertApprovedForWithdrawal(
|
|
121731
|
+
controller,
|
|
121732
|
+
withdrawalAddress.trim()
|
|
121733
|
+
);
|
|
121734
|
+
if (!approval.success) {
|
|
121735
|
+
return { success: false, error: approval.error.message };
|
|
121736
|
+
}
|
|
121737
|
+
}
|
|
121738
|
+
}
|
|
121396
121739
|
let pkpPublicKey;
|
|
121397
121740
|
let pkpEthAddress;
|
|
121398
121741
|
const pkpCache = this.cacheManager.getCache("pkp-data", {
|
|
@@ -122707,6 +123050,78 @@ Error data: ${errorData || "none"}`
|
|
|
122707
123050
|
);
|
|
122708
123051
|
return psm.getAvailableReserves(stablecoinAddress);
|
|
122709
123052
|
}
|
|
123053
|
+
/**
|
|
123054
|
+
* Execute a PSM stablecoin → UCD swap.
|
|
123055
|
+
* Handles stablecoin approval to the PSM contract if the current allowance is insufficient.
|
|
123056
|
+
*
|
|
123057
|
+
* @param params.stablecoinAddress - ERC-20 address of the stablecoin to swap in
|
|
123058
|
+
* @param params.amountWei - Stablecoin amount in native decimals (bigint)
|
|
123059
|
+
* @param params.minUcdOutWei - Minimum UCD to receive; reverts if below this (1% slippage guard)
|
|
123060
|
+
* @param params.signer - Connected signer for the approval and swap transactions
|
|
123061
|
+
*/
|
|
123062
|
+
async psmSwap(params) {
|
|
123063
|
+
const psmAddress = this.config.contractAddresses?.simplePsmV2;
|
|
123064
|
+
if (!psmAddress) {
|
|
123065
|
+
throw new Error(
|
|
123066
|
+
"SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2"
|
|
123067
|
+
);
|
|
123068
|
+
}
|
|
123069
|
+
const signerAddress = await params.signer.getAddress();
|
|
123070
|
+
const erc20Abi = [
|
|
123071
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
123072
|
+
"function approve(address spender, uint256 amount) returns (bool)"
|
|
123073
|
+
];
|
|
123074
|
+
const stablecoin = new Contract(params.stablecoinAddress, erc20Abi, params.signer);
|
|
123075
|
+
const allowance = await stablecoin.allowance(signerAddress, psmAddress);
|
|
123076
|
+
if (allowance < params.amountWei) {
|
|
123077
|
+
const approveTx = await stablecoin.approve(psmAddress, MaxUint256);
|
|
123078
|
+
await approveTx.wait();
|
|
123079
|
+
}
|
|
123080
|
+
const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
|
|
123081
|
+
const tx = await psm.swap(params.stablecoinAddress, params.amountWei, params.minUcdOutWei);
|
|
123082
|
+
const receipt = await tx.wait();
|
|
123083
|
+
if (!receipt)
|
|
123084
|
+
throw new Error("PSM swap transaction receipt unavailable");
|
|
123085
|
+
return { hash: tx.hash, blockNumber: receipt.blockNumber };
|
|
123086
|
+
}
|
|
123087
|
+
/**
|
|
123088
|
+
* Execute a PSM UCD → stablecoin redeem.
|
|
123089
|
+
* Handles UCD approval to UCDController (not PSM) to satisfy the M-4 burn allowance guard:
|
|
123090
|
+
* UCDToken.burn(from, amount) calls _spendAllowance(from, msg.sender=ucdController, amount).
|
|
123091
|
+
*
|
|
123092
|
+
* @param params.stablecoinAddress - ERC-20 address of the stablecoin to receive
|
|
123093
|
+
* @param params.ucdAmountWei - UCD amount to redeem (18 decimals, bigint)
|
|
123094
|
+
* @param params.minStablecoinOutWei - Minimum stablecoin to receive (slippage guard)
|
|
123095
|
+
* @param params.signer - Connected signer
|
|
123096
|
+
*/
|
|
123097
|
+
async psmRedeem(params) {
|
|
123098
|
+
const psmAddress = this.config.contractAddresses?.simplePsmV2;
|
|
123099
|
+
const ucdAddress = this.config.contractAddresses?.ucdToken;
|
|
123100
|
+
const ucdControllerAddress = this.config.contractAddresses?.ucdController;
|
|
123101
|
+
if (!psmAddress)
|
|
123102
|
+
throw new Error("SimplePSMV2 address not configured \u2014 provide contractAddresses.simplePsmV2");
|
|
123103
|
+
if (!ucdAddress)
|
|
123104
|
+
throw new Error("UCDToken address not configured \u2014 provide contractAddresses.ucdToken");
|
|
123105
|
+
if (!ucdControllerAddress)
|
|
123106
|
+
throw new Error("UCDController address not configured \u2014 provide contractAddresses.ucdController");
|
|
123107
|
+
const signerAddress = await params.signer.getAddress();
|
|
123108
|
+
const erc20Abi = [
|
|
123109
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
123110
|
+
"function approve(address spender, uint256 amount) returns (bool)"
|
|
123111
|
+
];
|
|
123112
|
+
const ucdToken = new Contract(ucdAddress, erc20Abi, params.signer);
|
|
123113
|
+
const allowance = await ucdToken.allowance(signerAddress, ucdControllerAddress);
|
|
123114
|
+
if (allowance < params.ucdAmountWei) {
|
|
123115
|
+
const approveTx = await ucdToken.approve(ucdControllerAddress, MaxUint256);
|
|
123116
|
+
await approveTx.wait();
|
|
123117
|
+
}
|
|
123118
|
+
const psm = SimplePSMV2__factory.connect(psmAddress, params.signer);
|
|
123119
|
+
const tx = await psm.redeem(params.stablecoinAddress, params.ucdAmountWei, params.minStablecoinOutWei);
|
|
123120
|
+
const receipt = await tx.wait();
|
|
123121
|
+
if (!receipt)
|
|
123122
|
+
throw new Error("PSM redeem transaction receipt unavailable");
|
|
123123
|
+
return { hash: tx.hash, blockNumber: receipt.blockNumber };
|
|
123124
|
+
}
|
|
122710
123125
|
/**
|
|
122711
123126
|
* Wait for the subgraph to index up to (and including) the given block number.
|
|
122712
123127
|
* Call after on-chain actions (createLoan, mintUCD, etc.) before querying the subgraph.
|
|
@@ -123896,6 +124311,7 @@ async function getPositionDelegate(positionId, provider, registryAddress) {
|
|
|
123896
124311
|
UCDConversions,
|
|
123897
124312
|
VALID_LIT_NETWORKS,
|
|
123898
124313
|
WeiConversions,
|
|
124314
|
+
WithdrawalAddressModule,
|
|
123899
124315
|
andThen,
|
|
123900
124316
|
assertProtocolNotPaused,
|
|
123901
124317
|
assertSafeServiceEndpoint,
|
|
@@ -123910,6 +124326,7 @@ async function getPositionDelegate(positionId, provider, registryAddress) {
|
|
|
123910
124326
|
createLoanQuery,
|
|
123911
124327
|
createMockTokenManager,
|
|
123912
124328
|
createPKPManager,
|
|
124329
|
+
createWithdrawalAddressModule,
|
|
123913
124330
|
failure,
|
|
123914
124331
|
fetchProtocolPauseStatus,
|
|
123915
124332
|
firstSuccess,
|