@gvnrdao/dh-sdk 0.0.332 → 0.0.333
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/graphs/diamond-hands.d.ts +37 -0
- package/dist/index.js +391 -186
- package/dist/index.mjs +415 -210
- package/dist/modules/withdrawal-address/withdrawal-address.module.d.ts +23 -0
- package/dist/utils/borrower-authorization-712.d.ts +81 -0
- package/dist/utils/extend-authorization.utils.d.ts +16 -15
- package/dist/utils/mint-authorization.utils.d.ts +50 -43
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1111,6 +1111,9 @@ var require_pkg_src = __commonJS({
|
|
|
1111
1111
|
});
|
|
1112
1112
|
var index_exports = {};
|
|
1113
1113
|
__export2(index_exports, {
|
|
1114
|
+
BORROWER_AUTHORIZATION_ENCODE_TYPES: () => BORROWER_AUTHORIZATION_ENCODE_TYPES,
|
|
1115
|
+
BORROWER_AUTHORIZATION_FIELDS: () => BORROWER_AUTHORIZATION_FIELDS,
|
|
1116
|
+
BORROWER_AUTHORIZATION_PRIMARY_TYPES: () => BORROWER_AUTHORIZATION_PRIMARY_TYPES,
|
|
1114
1117
|
CHIPOTLE_DEPLOYMENTS: () => CHIPOTLE_DEPLOYMENTS,
|
|
1115
1118
|
DEFAULT_CACHE_CONFIG: () => DEFAULT_CACHE_CONFIG,
|
|
1116
1119
|
DEFAULT_DEBUG_CONFIG: () => DEFAULT_DEBUG_CONFIG,
|
|
@@ -1123,6 +1126,8 @@ var require_pkg_src = __commonJS({
|
|
|
1123
1126
|
PerformanceTracker: () => PerformanceTracker,
|
|
1124
1127
|
RetryStrategy: () => RetryStrategy,
|
|
1125
1128
|
analyzeError: () => analyzeError,
|
|
1129
|
+
borrowerAuthorizationTypes: () => borrowerAuthorizationTypes,
|
|
1130
|
+
buildBorrowerAuthorizationDomain: () => buildBorrowerAuthorizationDomain,
|
|
1126
1131
|
calculateDelay: () => calculateDelay,
|
|
1127
1132
|
cidToHex: () => cidToHex,
|
|
1128
1133
|
classifyError: () => classifyError,
|
|
@@ -1369,30 +1374,30 @@ var require_pkg_src = __commonJS({
|
|
|
1369
1374
|
}
|
|
1370
1375
|
},
|
|
1371
1376
|
btcTransactionSigner: {
|
|
1372
|
-
cid: "
|
|
1377
|
+
cid: "QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf",
|
|
1373
1378
|
authorizedCidHex: cidToHex(
|
|
1374
|
-
"
|
|
1379
|
+
"QmVi1BYdxvCX3QUhXwPtP6FjWMzqSPtXzrS54YsXjTgjYf"
|
|
1375
1380
|
),
|
|
1376
1381
|
name: "Btc Transaction Signer",
|
|
1377
1382
|
description: "Production Btc Transaction Signer",
|
|
1378
1383
|
version: "1.1.1",
|
|
1379
1384
|
deployed: true,
|
|
1380
|
-
deployedAt:
|
|
1381
|
-
size:
|
|
1382
|
-
hash: "
|
|
1385
|
+
deployedAt: 1787923905597,
|
|
1386
|
+
size: 70646,
|
|
1387
|
+
hash: "37c3bb72a660c8275d92e1b73f9482742d86b64789480b9246304c0ca1bab47a"
|
|
1383
1388
|
},
|
|
1384
1389
|
ucdMintValidator: {
|
|
1385
|
-
cid: "
|
|
1390
|
+
cid: "QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc",
|
|
1386
1391
|
authorizedCidHex: cidToHex(
|
|
1387
|
-
"
|
|
1392
|
+
"QmUWR5fLiyimLT9TPXpYx3HgwNwkvR6MxjZ7hdeYCFodbc"
|
|
1388
1393
|
),
|
|
1389
1394
|
name: "Ucd Mint Validator",
|
|
1390
1395
|
description: "Production Ucd Mint Validator",
|
|
1391
1396
|
version: "1.2.1",
|
|
1392
1397
|
deployed: true,
|
|
1393
|
-
deployedAt:
|
|
1394
|
-
size:
|
|
1395
|
-
hash: "
|
|
1398
|
+
deployedAt: 1787923919527,
|
|
1399
|
+
size: 86197,
|
|
1400
|
+
hash: "c2d80939746cc37f65ef2f63c6a3215b929214a63f10c78144e1f5c98320dabf",
|
|
1396
1401
|
validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
|
|
1397
1402
|
pkp: {
|
|
1398
1403
|
publicKey: "0x041ab17cd91fc5c0b761eea6092d032807561b621b82c488826776e04a9158d61ba64d809a4729f0501289d980732cb06d8dfd06999dd9c8efd2f495dad78b31bb",
|
|
@@ -1400,17 +1405,17 @@ var require_pkg_src = __commonJS({
|
|
|
1400
1405
|
}
|
|
1401
1406
|
},
|
|
1402
1407
|
processPaymentValidator: {
|
|
1403
|
-
cid: "
|
|
1408
|
+
cid: "QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF",
|
|
1404
1409
|
authorizedCidHex: cidToHex(
|
|
1405
|
-
"
|
|
1410
|
+
"QmXmXuMRAjMLdgKGyTf9KQdGwYrDp8DxkiF44TvSXDf7wF"
|
|
1406
1411
|
),
|
|
1407
1412
|
name: "Process Payment Validator",
|
|
1408
1413
|
description: "Production Process Payment Validator",
|
|
1409
1414
|
version: "1.2.1",
|
|
1410
1415
|
deployed: true,
|
|
1411
|
-
deployedAt:
|
|
1412
|
-
size:
|
|
1413
|
-
hash: "
|
|
1416
|
+
deployedAt: 1787923987153,
|
|
1417
|
+
size: 82217,
|
|
1418
|
+
hash: "13defa19614215ab3b1fe88955d69e530d13a09475396af932fe0e213637da2f",
|
|
1414
1419
|
validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
|
|
1415
1420
|
pkp: {
|
|
1416
1421
|
publicKey: "0x04cfccb9b6c7addc79469c0e9fafebef4c70801302c62cdb26b610723a9b8527d23f98a40158c7340d83fd0e62d02b5ec74c12f7a86d98e8c6973b4811110f19ad",
|
|
@@ -1418,17 +1423,17 @@ var require_pkg_src = __commonJS({
|
|
|
1418
1423
|
}
|
|
1419
1424
|
},
|
|
1420
1425
|
extendPositionValidator: {
|
|
1421
|
-
cid: "
|
|
1426
|
+
cid: "QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m",
|
|
1422
1427
|
authorizedCidHex: cidToHex(
|
|
1423
|
-
"
|
|
1428
|
+
"QmU8h99EEVEsQkxroXiYqLsKZw9gNjE6N5CcTpE9aUc12m"
|
|
1424
1429
|
),
|
|
1425
1430
|
name: "Extend Position Validator",
|
|
1426
1431
|
description: "Production Extend Position Validator",
|
|
1427
1432
|
version: "1.2.1",
|
|
1428
1433
|
deployed: true,
|
|
1429
|
-
deployedAt:
|
|
1430
|
-
size:
|
|
1431
|
-
hash: "
|
|
1434
|
+
deployedAt: 1787923999294,
|
|
1435
|
+
size: 79975,
|
|
1436
|
+
hash: "31c1aaf883ef22f37681ddb0a4a949be5c05304b6aef178989475a2da935ef9a",
|
|
1432
1437
|
validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
|
|
1433
1438
|
pkp: {
|
|
1434
1439
|
publicKey: "0x04e52338f6a0c3362800f1a94c4c8f08be5030dde0fa217388c53d1c1a4790f4443c9f2886b2d2d8f4b75a9a156e9b028011b1a1cf7648da0e556aa980ec692836",
|
|
@@ -1436,17 +1441,17 @@ var require_pkg_src = __commonJS({
|
|
|
1436
1441
|
}
|
|
1437
1442
|
},
|
|
1438
1443
|
btcWithdrawal: {
|
|
1439
|
-
cid: "
|
|
1444
|
+
cid: "QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY",
|
|
1440
1445
|
authorizedCidHex: cidToHex(
|
|
1441
|
-
"
|
|
1446
|
+
"QmZQWET9pzrVD4gwQuSzYZmqa24JrUNtnnGFDd513sxMCY"
|
|
1442
1447
|
),
|
|
1443
1448
|
name: "Btc Withdrawal",
|
|
1444
1449
|
description: "Production Btc Withdrawal",
|
|
1445
1450
|
version: "1.2.7",
|
|
1446
1451
|
deployed: true,
|
|
1447
|
-
deployedAt:
|
|
1448
|
-
size:
|
|
1449
|
-
hash: "
|
|
1452
|
+
deployedAt: 1787924017769,
|
|
1453
|
+
size: 100069,
|
|
1454
|
+
hash: "4f8e27414e4da235e63d6ae1325c63f3d2fb956464515a21aa007a99935f0f13",
|
|
1450
1455
|
validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
|
|
1451
1456
|
pkp: {
|
|
1452
1457
|
publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
|
|
@@ -1558,30 +1563,30 @@ var require_pkg_src = __commonJS({
|
|
|
1558
1563
|
hash: "03ee5be239c91c735d2c95db89a0d1b77e602cfc18af8eb64b3281fddcd90a72"
|
|
1559
1564
|
},
|
|
1560
1565
|
agentModuleExecutor: {
|
|
1561
|
-
cid: "
|
|
1566
|
+
cid: "QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf",
|
|
1562
1567
|
authorizedCidHex: cidToHex(
|
|
1563
|
-
"
|
|
1568
|
+
"QmcD65vuremot5fsHVgp9JBAmei6gAaEtm5mdtLP7Yt9Kf"
|
|
1564
1569
|
),
|
|
1565
1570
|
name: "Agent Module Executor",
|
|
1566
1571
|
description: "Production Agent Module Executor",
|
|
1567
1572
|
version: "1.1.1",
|
|
1568
1573
|
deployed: true,
|
|
1569
|
-
deployedAt:
|
|
1570
|
-
size:
|
|
1571
|
-
hash: "
|
|
1574
|
+
deployedAt: 1787924032013,
|
|
1575
|
+
size: 13878,
|
|
1576
|
+
hash: "a7f0204700912e26e5a354bee13a1242a2baa218643b3bb22d28481f67f9baf4"
|
|
1572
1577
|
},
|
|
1573
1578
|
staleSpendRecoveryValidator: {
|
|
1574
|
-
cid: "
|
|
1579
|
+
cid: "QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8",
|
|
1575
1580
|
authorizedCidHex: cidToHex(
|
|
1576
|
-
"
|
|
1581
|
+
"QmNuwo4PT4AikAmhMdZgPWCb2mJDwWa9TnUqrqvofjbrT8"
|
|
1577
1582
|
),
|
|
1578
1583
|
name: "Stale Spend Recovery Validator",
|
|
1579
1584
|
description: "Production Stale Spend Recovery Validator",
|
|
1580
1585
|
version: "1.1.2",
|
|
1581
1586
|
deployed: true,
|
|
1582
|
-
deployedAt:
|
|
1583
|
-
size:
|
|
1584
|
-
hash: "
|
|
1587
|
+
deployedAt: 1787924048772,
|
|
1588
|
+
size: 41424,
|
|
1589
|
+
hash: "3c5f028d2bef4344768462993616d45e30d9d44ef126e04d6eb579821d57d99c",
|
|
1585
1590
|
validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
|
|
1586
1591
|
pkp: {
|
|
1587
1592
|
publicKey: "0x046da0ad6da7dd4a0063cbeac6f2bdb6a9889c2178b23470833356a8ee5630f7f0eee0db348d9d9aaaadd23eccf0063c8f68ee5e446abe30b882bf1de4c932bc21",
|
|
@@ -1589,17 +1594,17 @@ var require_pkg_src = __commonJS({
|
|
|
1589
1594
|
}
|
|
1590
1595
|
},
|
|
1591
1596
|
btcUtxoInvalidator: {
|
|
1592
|
-
cid: "
|
|
1597
|
+
cid: "QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf",
|
|
1593
1598
|
authorizedCidHex: cidToHex(
|
|
1594
|
-
"
|
|
1599
|
+
"QmaNGeWut7EiGwW4zUc2sFSt7RY5NWFgxYboyG333TwrJf"
|
|
1595
1600
|
),
|
|
1596
1601
|
name: "Btc Utxo Invalidator",
|
|
1597
1602
|
description: "Production Btc Utxo Invalidator",
|
|
1598
1603
|
version: "1.0.0",
|
|
1599
1604
|
deployed: true,
|
|
1600
|
-
deployedAt:
|
|
1601
|
-
size:
|
|
1602
|
-
hash: "
|
|
1605
|
+
deployedAt: 1787924133241,
|
|
1606
|
+
size: 66026,
|
|
1607
|
+
hash: "603bc50920d7f1dee77086f2c518d9e2922ab3858a419d3fbea8221ea3a6d9e9"
|
|
1603
1608
|
}
|
|
1604
1609
|
};
|
|
1605
1610
|
function getDeploymentsForNetwork(network) {
|
|
@@ -2360,6 +2365,101 @@ ${errorReport}`);
|
|
|
2360
2365
|
var SECONDS_PER_DAY = 86400;
|
|
2361
2366
|
var DAYS_PER_MONTH = 30;
|
|
2362
2367
|
var LIT_ACTION_ETH_RPC_TIMEOUT_MS = 8e3;
|
|
2368
|
+
var PINNED_CONTRACT_ADDRESSES = {
|
|
2369
|
+
1: {
|
|
2370
|
+
PositionManager: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
2371
|
+
LoanOperationsManagerModule: "0x2561974A40F1AEed1251d0A090A83cF8536FB9E9",
|
|
2372
|
+
BTCSpendAuthorizer: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
2373
|
+
BitcoinProviderRegistry: "0x4ab3Fb96e02893Ed6FAa61bad1918390c8DbbFFC",
|
|
2374
|
+
LITActionValidator: "0xD2c5d59c2CC5c409AC65ce0A817236aeC6869512",
|
|
2375
|
+
PositionDelegateRegistry: "0xf0aa2678aD4F60f49e8F7725089B5E86B7F8FE4C"
|
|
2376
|
+
},
|
|
2377
|
+
11155111: {
|
|
2378
|
+
PositionManager: "0x68e0507D982AEBF1D1C1Af8FBbd842327e2deeFF",
|
|
2379
|
+
LoanOperationsManagerModule: "0x3e05e760a87715207b7F4e8fD35EF7559BcA72C0",
|
|
2380
|
+
BTCSpendAuthorizer: "0xd7E9Eb5eE53f1d9ee55Dc162bBC7486bE437B6bD",
|
|
2381
|
+
BitcoinProviderRegistry: "0xbfA0c48B070D0a9A9CD27469AeacFD2d4261cEE2",
|
|
2382
|
+
LITActionValidator: "0x54eECd7C90F8A8fac27749Ba30BbE8AFBAccc856",
|
|
2383
|
+
PositionDelegateRegistry: "0x482369De283622E7b05731875ec137d4E3D208F9"
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
function getPinnedContractAddresses(chainId) {
|
|
2387
|
+
return PINNED_CONTRACT_ADDRESSES[chainId] ?? null;
|
|
2388
|
+
}
|
|
2389
|
+
var PROTOCOL_EIP712_DOMAIN_NAME = "DiamondHands.Protocol";
|
|
2390
|
+
var PROTOCOL_EIP712_DOMAIN_VERSION = "1";
|
|
2391
|
+
var BORROWER_AUTHORIZATION_PRIMARY_TYPES = {
|
|
2392
|
+
MINT: "MintRequest",
|
|
2393
|
+
REPAY: "RepayRequest",
|
|
2394
|
+
RENEW: "RenewRequest",
|
|
2395
|
+
WITHDRAW: "WithdrawRequest"
|
|
2396
|
+
};
|
|
2397
|
+
var BORROWER_AUTHORIZATION_FIELDS = {
|
|
2398
|
+
MintRequest: [
|
|
2399
|
+
{ name: "positionId", type: "bytes32" },
|
|
2400
|
+
{ name: "mintAmount", type: "uint256" },
|
|
2401
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
2402
|
+
],
|
|
2403
|
+
RepayRequest: [
|
|
2404
|
+
{ name: "positionId", type: "bytes32" },
|
|
2405
|
+
{ name: "paymentAmount", type: "uint256" },
|
|
2406
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
2407
|
+
],
|
|
2408
|
+
RenewRequest: [
|
|
2409
|
+
{ name: "positionId", type: "bytes32" },
|
|
2410
|
+
{ name: "selectedTerm", type: "uint256" },
|
|
2411
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
2412
|
+
],
|
|
2413
|
+
WithdrawRequest: [
|
|
2414
|
+
{ name: "positionId", type: "bytes32" },
|
|
2415
|
+
{ name: "totalDeduction", type: "uint256" },
|
|
2416
|
+
{ name: "withdrawalAddress", type: "string" },
|
|
2417
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
2418
|
+
]
|
|
2419
|
+
};
|
|
2420
|
+
var BORROWER_AUTHORIZATION_ENCODE_TYPES = {
|
|
2421
|
+
MintRequest: "MintRequest(bytes32 positionId,uint256 mintAmount,uint256 quantumTimestamp)",
|
|
2422
|
+
RepayRequest: "RepayRequest(bytes32 positionId,uint256 paymentAmount,uint256 quantumTimestamp)",
|
|
2423
|
+
RenewRequest: "RenewRequest(bytes32 positionId,uint256 selectedTerm,uint256 quantumTimestamp)",
|
|
2424
|
+
WithdrawRequest: "WithdrawRequest(bytes32 positionId,uint256 totalDeduction,string withdrawalAddress,uint256 quantumTimestamp)"
|
|
2425
|
+
};
|
|
2426
|
+
function borrowerAuthorizationTypes(primaryType) {
|
|
2427
|
+
const fields = BORROWER_AUTHORIZATION_FIELDS[primaryType];
|
|
2428
|
+
if (!fields) {
|
|
2429
|
+
throw new Error(
|
|
2430
|
+
`Unknown borrower authorization primary type "${primaryType}"; expected one of ${Object.keys(BORROWER_AUTHORIZATION_FIELDS).join(", ")}`
|
|
2431
|
+
);
|
|
2432
|
+
}
|
|
2433
|
+
return { [primaryType]: fields.map((field) => ({ ...field })) };
|
|
2434
|
+
}
|
|
2435
|
+
function buildBorrowerAuthorizationDomain(chainId, verifyingContractOverride) {
|
|
2436
|
+
if (!Number.isInteger(chainId) || chainId <= 0) {
|
|
2437
|
+
throw new Error(
|
|
2438
|
+
`Borrower authorization domain requires a positive integer chainId, got ${String(chainId)}`
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
const pinned = getPinnedContractAddresses(chainId);
|
|
2442
|
+
const pinnedLom = pinned?.LoanOperationsManagerModule;
|
|
2443
|
+
if (pinnedLom && verifyingContractOverride) {
|
|
2444
|
+
if (pinnedLom.toLowerCase() !== verifyingContractOverride.toLowerCase()) {
|
|
2445
|
+
throw new Error(
|
|
2446
|
+
`Refusing a caller-supplied verifyingContract that contradicts the pin for chainId ${chainId}: caller ${verifyingContractOverride}, pinned ${pinnedLom}`
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
const verifyingContract = pinnedLom ?? verifyingContractOverride;
|
|
2451
|
+
if (!verifyingContract) {
|
|
2452
|
+
throw new Error(
|
|
2453
|
+
`No pinned LoanOperationsManagerModule for chainId ${chainId} and no verifyingContract supplied; refusing to build a borrower authorization domain without one`
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
2456
|
+
return {
|
|
2457
|
+
name: PROTOCOL_EIP712_DOMAIN_NAME,
|
|
2458
|
+
version: PROTOCOL_EIP712_DOMAIN_VERSION,
|
|
2459
|
+
chainId,
|
|
2460
|
+
verifyingContract
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2363
2463
|
var EVMChain = /* @__PURE__ */ ((EVMChain3) => {
|
|
2364
2464
|
EVMChain3["SEPOLIA"] = "sepolia";
|
|
2365
2465
|
EVMChain3["ETHEREUM"] = "ethereum";
|
|
@@ -5654,7 +5754,7 @@ var init_network_configs = __esm({
|
|
|
5654
5754
|
});
|
|
5655
5755
|
|
|
5656
5756
|
// src/modules/diamond-hands-sdk.ts
|
|
5657
|
-
import { Contract as Contract9, Interface as Interface5, JsonRpcProvider, AbiCoder as AbiCoder2, keccak256 as
|
|
5757
|
+
import { Contract as Contract9, Interface as Interface5, JsonRpcProvider, AbiCoder as AbiCoder2, keccak256 as keccak2565, solidityPackedKeccak256 as solidityPackedKeccak2564, toUtf8Bytes as toUtf8Bytes5, getBytes as getBytes4, zeroPadValue as zeroPadValue5, toBeHex as toBeHex2, parseEther, formatEther, formatUnits, computeAddress, Signature, ZeroHash, ZeroAddress as ZeroAddress3, MaxUint256 } from "ethers";
|
|
5658
5758
|
|
|
5659
5759
|
// src/types/result.ts
|
|
5660
5760
|
function success(value) {
|
|
@@ -6265,6 +6365,80 @@ async function awaitSafeSubmissionWindowOnChain(signatureQuantum, chainNow, slee
|
|
|
6265
6365
|
return { waited: waitedSeconds > 0, waitedSeconds };
|
|
6266
6366
|
}
|
|
6267
6367
|
|
|
6368
|
+
// src/utils/borrower-authorization-712.ts
|
|
6369
|
+
init_deployment_addresses();
|
|
6370
|
+
import { TypedDataEncoder } from "ethers";
|
|
6371
|
+
var BORROWER_AUTHORIZATION_712_DOMAIN_NAME = "DiamondHands.Protocol";
|
|
6372
|
+
var BORROWER_AUTHORIZATION_712_DOMAIN_VERSION = "1";
|
|
6373
|
+
var BORROWER_AUTHORIZATION_712_FIELDS = {
|
|
6374
|
+
MintRequest: [
|
|
6375
|
+
{ name: "positionId", type: "bytes32" },
|
|
6376
|
+
{ name: "mintAmount", type: "uint256" },
|
|
6377
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
6378
|
+
],
|
|
6379
|
+
RepayRequest: [
|
|
6380
|
+
{ name: "positionId", type: "bytes32" },
|
|
6381
|
+
{ name: "paymentAmount", type: "uint256" },
|
|
6382
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
6383
|
+
],
|
|
6384
|
+
RenewRequest: [
|
|
6385
|
+
{ name: "positionId", type: "bytes32" },
|
|
6386
|
+
{ name: "selectedTerm", type: "uint256" },
|
|
6387
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
6388
|
+
],
|
|
6389
|
+
WithdrawRequest: [
|
|
6390
|
+
{ name: "positionId", type: "bytes32" },
|
|
6391
|
+
{ name: "totalDeduction", type: "uint256" },
|
|
6392
|
+
{ name: "withdrawalAddress", type: "string" },
|
|
6393
|
+
{ name: "quantumTimestamp", type: "uint256" }
|
|
6394
|
+
]
|
|
6395
|
+
};
|
|
6396
|
+
function borrowerAuthorization712Types(primaryType) {
|
|
6397
|
+
const fields = BORROWER_AUTHORIZATION_712_FIELDS[primaryType];
|
|
6398
|
+
if (!fields) {
|
|
6399
|
+
throw new Error(
|
|
6400
|
+
`Unknown borrower authorization primary type "${primaryType}"; expected one of ` + Object.keys(BORROWER_AUTHORIZATION_712_FIELDS).join(", ")
|
|
6401
|
+
);
|
|
6402
|
+
}
|
|
6403
|
+
return { [primaryType]: fields.map((field) => ({ ...field })) };
|
|
6404
|
+
}
|
|
6405
|
+
function buildBorrowerAuthorization712Domain(chainId) {
|
|
6406
|
+
if (!Number.isInteger(chainId) || chainId <= 0) {
|
|
6407
|
+
throw new Error(
|
|
6408
|
+
`Borrower authorization domain requires a positive integer chainId, got ${String(chainId)}`
|
|
6409
|
+
);
|
|
6410
|
+
}
|
|
6411
|
+
const deployment = Object.values(ALL_DEPLOYMENTS).find(
|
|
6412
|
+
(d) => d.chainId === chainId
|
|
6413
|
+
);
|
|
6414
|
+
const verifyingContract = deployment?.contracts?.LoanOperationsManagerModule;
|
|
6415
|
+
if (!verifyingContract) {
|
|
6416
|
+
throw new Error(
|
|
6417
|
+
`No LoanOperationsManagerModule deployment known for chainId ${chainId}; refusing to build a borrower authorization domain without one`
|
|
6418
|
+
);
|
|
6419
|
+
}
|
|
6420
|
+
return {
|
|
6421
|
+
name: BORROWER_AUTHORIZATION_712_DOMAIN_NAME,
|
|
6422
|
+
version: BORROWER_AUTHORIZATION_712_DOMAIN_VERSION,
|
|
6423
|
+
chainId,
|
|
6424
|
+
verifyingContract
|
|
6425
|
+
};
|
|
6426
|
+
}
|
|
6427
|
+
async function signBorrowerAuthorization712(signer, primaryType, chainId, message) {
|
|
6428
|
+
const signTypedData = signer.signTypedData;
|
|
6429
|
+
if (typeof signTypedData !== "function") {
|
|
6430
|
+
throw new Error(
|
|
6431
|
+
`Signer has no signTypedData \u2014 cannot produce an EIP-712 ${primaryType}. Wallets without typed-data support must supply the signature via an authorizationProvider instead of a connected signer.`
|
|
6432
|
+
);
|
|
6433
|
+
}
|
|
6434
|
+
return signTypedData.call(
|
|
6435
|
+
signer,
|
|
6436
|
+
buildBorrowerAuthorization712Domain(chainId),
|
|
6437
|
+
borrowerAuthorization712Types(primaryType),
|
|
6438
|
+
message
|
|
6439
|
+
);
|
|
6440
|
+
}
|
|
6441
|
+
|
|
6268
6442
|
// src/utils/mint-authorization.utils.ts
|
|
6269
6443
|
var PKP_NFT_ABI = [
|
|
6270
6444
|
"function getPubkey(uint256 tokenId) external view returns (bytes memory)"
|
|
@@ -6278,29 +6452,11 @@ async function generateMintAuthorization(positionId, amount, chainId, signerOrPr
|
|
|
6278
6452
|
const signer = signerOrPrecomputed;
|
|
6279
6453
|
const timestamp = calculateNextQuantumTimestamp();
|
|
6280
6454
|
const action = "mint-ucd";
|
|
6281
|
-
const
|
|
6282
|
-
const types = [
|
|
6283
|
-
"bytes32",
|
|
6284
|
-
// positionId
|
|
6285
|
-
"uint256",
|
|
6286
|
-
// timestamp
|
|
6287
|
-
"uint256",
|
|
6288
|
-
// chainId
|
|
6289
|
-
"uint256",
|
|
6290
|
-
// amount
|
|
6291
|
-
"bytes32"
|
|
6292
|
-
// actionHash
|
|
6293
|
-
];
|
|
6294
|
-
const values = [
|
|
6455
|
+
const signature = await signBorrowerAuthorization712(signer, "MintRequest", chainId, {
|
|
6295
6456
|
positionId,
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
actionHash
|
|
6300
|
-
];
|
|
6301
|
-
const messageHash = solidityPackedKeccak256(types, values);
|
|
6302
|
-
const messageHashBytes = getBytes(messageHash);
|
|
6303
|
-
const signature = await signer.signMessage(messageHashBytes);
|
|
6457
|
+
mintAmount: amount.toString(),
|
|
6458
|
+
quantumTimestamp: timestamp
|
|
6459
|
+
});
|
|
6304
6460
|
return {
|
|
6305
6461
|
positionId,
|
|
6306
6462
|
timestamp,
|
|
@@ -6337,44 +6493,17 @@ async function generatePaymentAuthorization(positionId, amount, chainId, signerO
|
|
|
6337
6493
|
throw new Error(`timestamp must be a number, got ${typeof timestamp}`);
|
|
6338
6494
|
}
|
|
6339
6495
|
const action = "make-payment";
|
|
6340
|
-
const actionHash = keccak256(toUtf8Bytes(action));
|
|
6341
|
-
if (typeof actionHash !== "string") {
|
|
6342
|
-
throw new Error(`actionHash must be a string, got ${typeof actionHash}`);
|
|
6343
|
-
}
|
|
6344
|
-
const types = [
|
|
6345
|
-
"bytes32",
|
|
6346
|
-
// positionId
|
|
6347
|
-
"uint256",
|
|
6348
|
-
// timestamp
|
|
6349
|
-
"uint256",
|
|
6350
|
-
// chainId
|
|
6351
|
-
"uint256",
|
|
6352
|
-
// amount
|
|
6353
|
-
"bytes32"
|
|
6354
|
-
// actionHash
|
|
6355
|
-
];
|
|
6356
6496
|
const amountStr = amount.toString();
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
}
|
|
6362
|
-
const values = [positionId, timestamp, chainId, amountStr, actionHash];
|
|
6363
|
-
for (let i = 0; i < values.length; i++) {
|
|
6364
|
-
if (typeof values[i] === "object" && values[i] !== null) {
|
|
6365
|
-
throw new Error(
|
|
6366
|
-
`Value at index ${i} is an object: ${JSON.stringify(values[i])}`
|
|
6367
|
-
);
|
|
6368
|
-
}
|
|
6369
|
-
}
|
|
6370
|
-
const messageHash = solidityPackedKeccak256(types, values);
|
|
6371
|
-
const messageHashBytes = getBytes(messageHash);
|
|
6372
|
-
const signature = await signer.signMessage(messageHashBytes);
|
|
6497
|
+
const signature = await signBorrowerAuthorization712(signer, "RepayRequest", chainId, {
|
|
6498
|
+
positionId,
|
|
6499
|
+
paymentAmount: amountStr,
|
|
6500
|
+
quantumTimestamp: timestamp
|
|
6501
|
+
});
|
|
6373
6502
|
return {
|
|
6374
6503
|
positionId,
|
|
6375
6504
|
timestamp,
|
|
6376
6505
|
chainId,
|
|
6377
|
-
amount:
|
|
6506
|
+
amount: amountStr,
|
|
6378
6507
|
action,
|
|
6379
6508
|
signature
|
|
6380
6509
|
};
|
|
@@ -6461,32 +6590,12 @@ async function generateWithdrawAuthorization(positionId, amount, chainId, signer
|
|
|
6461
6590
|
const signer = signerOrPrecomputed;
|
|
6462
6591
|
const timestamp = calculateNextQuantumTimestamp();
|
|
6463
6592
|
const action = "withdraw-btc";
|
|
6464
|
-
const
|
|
6465
|
-
const types = [
|
|
6466
|
-
"bytes32",
|
|
6467
|
-
// positionId
|
|
6468
|
-
"uint256",
|
|
6469
|
-
// timestamp
|
|
6470
|
-
"uint256",
|
|
6471
|
-
// chainId
|
|
6472
|
-
"uint256",
|
|
6473
|
-
// amount (in satoshis)
|
|
6474
|
-
"string",
|
|
6475
|
-
// destinationAddress (Bitcoin address)
|
|
6476
|
-
"bytes32"
|
|
6477
|
-
// actionHash
|
|
6478
|
-
];
|
|
6479
|
-
const values = [
|
|
6593
|
+
const signature = await signBorrowerAuthorization712(signer, "WithdrawRequest", chainId, {
|
|
6480
6594
|
positionId,
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
actionHash
|
|
6486
|
-
];
|
|
6487
|
-
const messageHash = solidityPackedKeccak256(types, values);
|
|
6488
|
-
const messageHashBytes = getBytes(messageHash);
|
|
6489
|
-
const signature = await signer.signMessage(messageHashBytes);
|
|
6595
|
+
totalDeduction: amount.toString(),
|
|
6596
|
+
withdrawalAddress: destinationAddress,
|
|
6597
|
+
quantumTimestamp: timestamp
|
|
6598
|
+
});
|
|
6490
6599
|
return {
|
|
6491
6600
|
positionId,
|
|
6492
6601
|
timestamp,
|
|
@@ -6528,7 +6637,6 @@ async function generateBalanceConfirmationAuthorization(positionId, chainId, sig
|
|
|
6528
6637
|
}
|
|
6529
6638
|
|
|
6530
6639
|
// src/utils/extend-authorization.utils.ts
|
|
6531
|
-
import { keccak256 as keccak2562, toUtf8Bytes as toUtf8Bytes2, solidityPackedKeccak256 as solidityPackedKeccak2562, getBytes as getBytes2 } from "ethers";
|
|
6532
6640
|
async function generateExtendAuthorization(positionId, newTerm, chainId, signerOrPrecomputed) {
|
|
6533
6641
|
if (typeof signerOrPrecomputed === "object" && "signature" in signerOrPrecomputed && !("signMessage" in signerOrPrecomputed)) {
|
|
6534
6642
|
const { timestamp: timestamp2, signature: signature2 } = signerOrPrecomputed;
|
|
@@ -6538,29 +6646,11 @@ async function generateExtendAuthorization(positionId, newTerm, chainId, signerO
|
|
|
6538
6646
|
const signer = signerOrPrecomputed;
|
|
6539
6647
|
const timestamp = calculateNextQuantumTimestamp();
|
|
6540
6648
|
const action = "extend-position";
|
|
6541
|
-
const
|
|
6542
|
-
const types = [
|
|
6543
|
-
"bytes32",
|
|
6544
|
-
// positionId
|
|
6545
|
-
"uint256",
|
|
6546
|
-
// timestamp
|
|
6547
|
-
"uint256",
|
|
6548
|
-
// chainId
|
|
6549
|
-
"uint256",
|
|
6550
|
-
// newTerm (extension term in months)
|
|
6551
|
-
"bytes32"
|
|
6552
|
-
// actionHash
|
|
6553
|
-
];
|
|
6554
|
-
const values = [
|
|
6649
|
+
const signature = await signBorrowerAuthorization712(signer, "RenewRequest", chainId, {
|
|
6555
6650
|
positionId,
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
actionHash
|
|
6560
|
-
];
|
|
6561
|
-
const messageHash = solidityPackedKeccak2562(types, values);
|
|
6562
|
-
const messageHashBytes = getBytes2(messageHash);
|
|
6563
|
-
const signature = await signer.signMessage(messageHashBytes);
|
|
6651
|
+
selectedTerm: newTerm,
|
|
6652
|
+
quantumTimestamp: timestamp
|
|
6653
|
+
});
|
|
6564
6654
|
return {
|
|
6565
6655
|
positionId,
|
|
6566
6656
|
timestamp,
|
|
@@ -7501,10 +7591,10 @@ async function reconcileAuthorizedSpend(spend, esploraBaseUrl, httpGetJson = def
|
|
|
7501
7591
|
|
|
7502
7592
|
// src/utils/stale-spend-invalidate-message.ts
|
|
7503
7593
|
import {
|
|
7504
|
-
keccak256 as
|
|
7505
|
-
toUtf8Bytes as
|
|
7506
|
-
solidityPackedKeccak256 as
|
|
7507
|
-
getBytes as
|
|
7594
|
+
keccak256 as keccak2562,
|
|
7595
|
+
toUtf8Bytes as toUtf8Bytes2,
|
|
7596
|
+
solidityPackedKeccak256 as solidityPackedKeccak2562,
|
|
7597
|
+
getBytes as getBytes2,
|
|
7508
7598
|
zeroPadValue
|
|
7509
7599
|
} from "ethers";
|
|
7510
7600
|
var RECOVERY_INVALIDATE_ACTION = "btc-utxo-invalidator";
|
|
@@ -7515,8 +7605,8 @@ function buildInvalidateMessageHash(params) {
|
|
|
7515
7605
|
params.positionId.startsWith("0x") ? params.positionId : `0x${params.positionId}`,
|
|
7516
7606
|
32
|
|
7517
7607
|
);
|
|
7518
|
-
const actionHash =
|
|
7519
|
-
return
|
|
7608
|
+
const actionHash = keccak2562(toUtf8Bytes2(RECOVERY_INVALIDATE_ACTION));
|
|
7609
|
+
return solidityPackedKeccak2562(
|
|
7520
7610
|
[
|
|
7521
7611
|
"bytes32",
|
|
7522
7612
|
// positionId
|
|
@@ -7562,7 +7652,7 @@ async function buildInvalidateStaleSpendEnvelope(params) {
|
|
|
7562
7652
|
utxoTxid,
|
|
7563
7653
|
utxoVout
|
|
7564
7654
|
});
|
|
7565
|
-
const signature = await signer.signMessage(
|
|
7655
|
+
const signature = await signer.signMessage(getBytes2(messageHash));
|
|
7566
7656
|
const borrowerAddress = await signer.getAddress();
|
|
7567
7657
|
return {
|
|
7568
7658
|
positionId,
|
|
@@ -7577,7 +7667,7 @@ async function buildInvalidateStaleSpendEnvelope(params) {
|
|
|
7577
7667
|
}
|
|
7578
7668
|
|
|
7579
7669
|
// src/utils/btc-withdrawal-message.ts
|
|
7580
|
-
import { keccak256 as
|
|
7670
|
+
import { keccak256 as keccak2563, toUtf8Bytes as toUtf8Bytes3, solidityPackedKeccak256 as solidityPackedKeccak2563, getBytes as getBytes3, zeroPadValue as zeroPadValue2 } from "ethers";
|
|
7581
7671
|
var QUANTUM_SECONDS2 = 60;
|
|
7582
7672
|
var QUANTUM_SAFE_THRESHOLD2 = 40;
|
|
7583
7673
|
function hashBtcInputSet(utxos) {
|
|
@@ -7608,7 +7698,7 @@ function hashBtcInputSet(utxos) {
|
|
|
7608
7698
|
seen.add(key);
|
|
7609
7699
|
}
|
|
7610
7700
|
const canonical = normalized.sort((a, b) => a.txid < b.txid ? -1 : a.txid > b.txid ? 1 : a.vout - b.vout).map((u) => `${u.txid}:${u.vout}:${u.value}`).join("|");
|
|
7611
|
-
return
|
|
7701
|
+
return keccak2563(toUtf8Bytes3(canonical));
|
|
7612
7702
|
}
|
|
7613
7703
|
async function buildBtcExecuteEnvelope(params) {
|
|
7614
7704
|
const {
|
|
@@ -7653,15 +7743,15 @@ async function buildBtcExecuteEnvelope(params) {
|
|
|
7653
7743
|
} else {
|
|
7654
7744
|
timestamp = currentQuantumStart;
|
|
7655
7745
|
}
|
|
7656
|
-
const actionHash =
|
|
7657
|
-
|
|
7746
|
+
const actionHash = keccak2563(
|
|
7747
|
+
toUtf8Bytes3("execute-btc-withdrawal")
|
|
7658
7748
|
);
|
|
7659
7749
|
const utxoIdentifier = `${txid}:${vout}`;
|
|
7660
7750
|
const positionIdBytes32 = zeroPadValue2(
|
|
7661
7751
|
positionId.startsWith("0x") ? positionId : `0x${positionId}`,
|
|
7662
7752
|
32
|
|
7663
7753
|
);
|
|
7664
|
-
const messageHash =
|
|
7754
|
+
const messageHash = solidityPackedKeccak2563(
|
|
7665
7755
|
[
|
|
7666
7756
|
"bytes32",
|
|
7667
7757
|
// positionId
|
|
@@ -7694,7 +7784,7 @@ async function buildBtcExecuteEnvelope(params) {
|
|
|
7694
7784
|
actionHash
|
|
7695
7785
|
]
|
|
7696
7786
|
);
|
|
7697
|
-
const userSignature = await signer.signMessage(
|
|
7787
|
+
const userSignature = await signer.signMessage(getBytes3(messageHash));
|
|
7698
7788
|
const borrowerAddress = await signer.getAddress();
|
|
7699
7789
|
return {
|
|
7700
7790
|
positionId,
|
|
@@ -10795,7 +10885,8 @@ function createLoanQuery(config) {
|
|
|
10795
10885
|
}
|
|
10796
10886
|
|
|
10797
10887
|
// src/modules/withdrawal-address/withdrawal-address.module.ts
|
|
10798
|
-
import { keccak256 as
|
|
10888
|
+
import { keccak256 as keccak2564, toUtf8Bytes as toUtf8Bytes4, ZeroAddress as ZeroAddress2 } from "ethers";
|
|
10889
|
+
var STATIC_CALL_DIAGNOSTIC_TIMEOUT_MS = 5e3;
|
|
10799
10890
|
var WithdrawalAddressModule = class {
|
|
10800
10891
|
config;
|
|
10801
10892
|
graphClient;
|
|
@@ -10830,7 +10921,7 @@ var WithdrawalAddressModule = class {
|
|
|
10830
10921
|
}
|
|
10831
10922
|
/** keccak256 of the canonicalized address — matches the on-chain key. */
|
|
10832
10923
|
static addressHash(btcAddress) {
|
|
10833
|
-
return
|
|
10924
|
+
return keccak2564(toUtf8Bytes4(normalizeBitcoinAddress(btcAddress)));
|
|
10834
10925
|
}
|
|
10835
10926
|
/**
|
|
10836
10927
|
* Add a Bitcoin address to the caller's allowlist. It becomes usable only
|
|
@@ -10840,13 +10931,17 @@ var WithdrawalAddressModule = class {
|
|
|
10840
10931
|
const reg = this.getRegistry();
|
|
10841
10932
|
if (!reg.success)
|
|
10842
10933
|
return reg;
|
|
10934
|
+
const normalized = normalizeBitcoinAddress(btcAddress);
|
|
10843
10935
|
try {
|
|
10844
|
-
const tx = await reg.value.addAddress(
|
|
10845
|
-
normalizeBitcoinAddress(btcAddress)
|
|
10846
|
-
);
|
|
10936
|
+
const tx = await reg.value.addAddress(normalized);
|
|
10847
10937
|
return success(tx);
|
|
10848
10938
|
} catch (error) {
|
|
10849
|
-
return this.txFailure(
|
|
10939
|
+
return this.txFailure(
|
|
10940
|
+
"addAddress",
|
|
10941
|
+
error,
|
|
10942
|
+
btcAddress,
|
|
10943
|
+
await this.staticCallDiagnostic(reg.value, "addAddress", normalized)
|
|
10944
|
+
);
|
|
10850
10945
|
}
|
|
10851
10946
|
}
|
|
10852
10947
|
/** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
|
|
@@ -10854,13 +10949,17 @@ var WithdrawalAddressModule = class {
|
|
|
10854
10949
|
const reg = this.getRegistry();
|
|
10855
10950
|
if (!reg.success)
|
|
10856
10951
|
return reg;
|
|
10952
|
+
const normalized = normalizeBitcoinAddress(btcAddress);
|
|
10857
10953
|
try {
|
|
10858
|
-
const tx = await reg.value.removeAddress(
|
|
10859
|
-
normalizeBitcoinAddress(btcAddress)
|
|
10860
|
-
);
|
|
10954
|
+
const tx = await reg.value.removeAddress(normalized);
|
|
10861
10955
|
return success(tx);
|
|
10862
10956
|
} catch (error) {
|
|
10863
|
-
return this.txFailure(
|
|
10957
|
+
return this.txFailure(
|
|
10958
|
+
"removeAddress",
|
|
10959
|
+
error,
|
|
10960
|
+
btcAddress,
|
|
10961
|
+
await this.staticCallDiagnostic(reg.value, "removeAddress", normalized)
|
|
10962
|
+
);
|
|
10864
10963
|
}
|
|
10865
10964
|
}
|
|
10866
10965
|
/**
|
|
@@ -10956,16 +11055,59 @@ var WithdrawalAddressModule = class {
|
|
|
10956
11055
|
}
|
|
10957
11056
|
return success(void 0);
|
|
10958
11057
|
}
|
|
10959
|
-
|
|
11058
|
+
/**
|
|
11059
|
+
* Ask the node for the reason a failed write did not carry.
|
|
11060
|
+
*
|
|
11061
|
+
* A failing `eth_estimateGas` frequently answers with NOTHING to decode — ethers renders that
|
|
11062
|
+
* as `missing revert data ... data=null, reason=null, revert=null`, which names no cause and
|
|
11063
|
+
* cannot distinguish "the contract rejected this" from "the RPC hiccuped". An `eth_call` of the
|
|
11064
|
+
* same calldata usually does carry the revert reason or custom-error selector, so this runs one
|
|
11065
|
+
* and folds the answer into the reported error.
|
|
11066
|
+
*
|
|
11067
|
+
* Three deliberate properties:
|
|
11068
|
+
*
|
|
11069
|
+
* 1. It runs ONLY after the write has already failed. Gating the write on a static call would
|
|
11070
|
+
* let a flaky endpoint — precisely the condition this exists to diagnose — block an add that
|
|
11071
|
+
* would otherwise have succeeded.
|
|
11072
|
+
* 2. It costs NO extra signature. `staticCall` is `eth_call`: a node read, never a wallet prompt.
|
|
11073
|
+
* 3. It can never throw. A diagnostic that escapes would replace the real cause with itself.
|
|
11074
|
+
* (The `try/catch` here is the authorized exception to CLAUDE.md's forbidden-patterns rule;
|
|
11075
|
+
* it swallows nothing — every branch returns text that is reported alongside the original.)
|
|
11076
|
+
*
|
|
11077
|
+
* A static call that SUCCEEDS is itself a finding: the contract accepts this call, so the
|
|
11078
|
+
* failure lay outside contract logic (RPC, gas, or nonce).
|
|
11079
|
+
*/
|
|
11080
|
+
async staticCallDiagnostic(registry, op, normalizedAddress) {
|
|
11081
|
+
try {
|
|
11082
|
+
await Promise.race([
|
|
11083
|
+
registry[op].staticCall(normalizedAddress),
|
|
11084
|
+
// The failure being diagnosed is often an unresponsive endpoint, so the diagnostic must
|
|
11085
|
+
// not inherit that hang — the user is waiting on this error message.
|
|
11086
|
+
new Promise(
|
|
11087
|
+
(_, reject) => setTimeout(
|
|
11088
|
+
() => reject(new Error("static call timed out after 5s")),
|
|
11089
|
+
STATIC_CALL_DIAGNOSTIC_TIMEOUT_MS
|
|
11090
|
+
)
|
|
11091
|
+
)
|
|
11092
|
+
]);
|
|
11093
|
+
return "static call SUCCEEDED \u2014 the contract accepts this call, so the failure was not contract logic (RPC, gas, or nonce)";
|
|
11094
|
+
} catch (diagnostic) {
|
|
11095
|
+
const code = typeof diagnostic === "object" && diagnostic !== null ? diagnostic.code : void 0;
|
|
11096
|
+
const msg = diagnostic instanceof Error ? diagnostic.message : String(diagnostic);
|
|
11097
|
+
return typeof code === "string" ? `static call reverted [${code}]: ${msg}` : `static call failed: ${msg}`;
|
|
11098
|
+
}
|
|
11099
|
+
}
|
|
11100
|
+
txFailure(op, error, context, diagnostic) {
|
|
10960
11101
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11102
|
+
const detail = diagnostic ? `${msg} \u2014 ${diagnostic}` : msg;
|
|
10961
11103
|
return failure(
|
|
10962
11104
|
new SDKError({
|
|
10963
11105
|
code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
|
|
10964
|
-
message: `WithdrawalAddressRegistry.${op} failed: ${
|
|
11106
|
+
message: `WithdrawalAddressRegistry.${op} failed: ${detail}`,
|
|
10965
11107
|
category: "CONTRACT" /* CONTRACT */,
|
|
10966
11108
|
severity: "MEDIUM" /* MEDIUM */,
|
|
10967
11109
|
originalError: error instanceof Error ? error : new Error(String(error)),
|
|
10968
|
-
context: { op, context }
|
|
11110
|
+
context: { op, context, diagnostic }
|
|
10969
11111
|
})
|
|
10970
11112
|
);
|
|
10971
11113
|
}
|
|
@@ -12056,6 +12198,47 @@ function normalizePkpId2(pkpId) {
|
|
|
12056
12198
|
}
|
|
12057
12199
|
return pkpId;
|
|
12058
12200
|
}
|
|
12201
|
+
function applyLoanEventsFilter(events, opts) {
|
|
12202
|
+
const { wantsEvent, fromTimestamp, toTimestamp, fromBlock, toBlock, limit } = opts;
|
|
12203
|
+
const inBounds = (e) => {
|
|
12204
|
+
const ts = e?.timestamp;
|
|
12205
|
+
const bn = e?.blockNumber;
|
|
12206
|
+
try {
|
|
12207
|
+
if (fromTimestamp !== void 0 && ts !== void 0 && BigInt(ts) < BigInt(fromTimestamp))
|
|
12208
|
+
return false;
|
|
12209
|
+
if (toTimestamp !== void 0 && ts !== void 0 && BigInt(ts) > BigInt(toTimestamp))
|
|
12210
|
+
return false;
|
|
12211
|
+
if (fromBlock !== void 0 && bn !== void 0 && BigInt(bn) < BigInt(fromBlock))
|
|
12212
|
+
return false;
|
|
12213
|
+
if (toBlock !== void 0 && bn !== void 0 && BigInt(bn) > BigInt(toBlock))
|
|
12214
|
+
return false;
|
|
12215
|
+
} catch {
|
|
12216
|
+
return true;
|
|
12217
|
+
}
|
|
12218
|
+
return true;
|
|
12219
|
+
};
|
|
12220
|
+
const narrow = (list, kind) => wantsEvent(kind) ? (list ?? []).filter(inBounds).slice(0, limit) : [];
|
|
12221
|
+
const single = (value, kind) => value && wantsEvent(kind) && inBounds(value) ? value : void 0;
|
|
12222
|
+
const filtered = {
|
|
12223
|
+
...events,
|
|
12224
|
+
positionCreated: single(events.positionCreated, "positionCreated"),
|
|
12225
|
+
payments: narrow(events.payments, "payment"),
|
|
12226
|
+
statusUpdates: narrow(events.statusUpdates, "status"),
|
|
12227
|
+
liquidation: single(events.liquidation, "liquidation"),
|
|
12228
|
+
mints: narrow(events.mints, "mint"),
|
|
12229
|
+
withdrawals: narrow(events.withdrawals, "withdrawal"),
|
|
12230
|
+
renewals: narrow(events.renewals, "renewal"),
|
|
12231
|
+
operationFailures: narrow(events.operationFailures, "operationFailure"),
|
|
12232
|
+
mintRequests: narrow(events.mintRequests, "mintRequest"),
|
|
12233
|
+
burnRequests: narrow(events.burnRequests, "burnRequest"),
|
|
12234
|
+
collateralEvents: narrow(events.collateralEvents, "collateralEvent"),
|
|
12235
|
+
mintingFees: narrow(events.mintingFees, "mintingFee"),
|
|
12236
|
+
renewalFees: narrow(events.renewalFees, "renewalFee"),
|
|
12237
|
+
totalEvents: 0
|
|
12238
|
+
};
|
|
12239
|
+
filtered.totalEvents = (filtered.positionCreated ? 1 : 0) + (filtered.liquidation ? 1 : 0) + filtered.payments.length + filtered.statusUpdates.length + filtered.mints.length + filtered.withdrawals.length + filtered.renewals.length + filtered.operationFailures.length + filtered.mintRequests.length + filtered.burnRequests.length + filtered.collateralEvents.length + filtered.mintingFees.length + filtered.renewalFees.length;
|
|
12240
|
+
return filtered;
|
|
12241
|
+
}
|
|
12059
12242
|
function hasLoanEventsFilter(filter) {
|
|
12060
12243
|
if (!filter)
|
|
12061
12244
|
return false;
|
|
@@ -13212,32 +13395,24 @@ var DiamondHandsGraph = class {
|
|
|
13212
13395
|
limit = 1e3,
|
|
13213
13396
|
orderDirection = "desc"
|
|
13214
13397
|
} = filter || {};
|
|
13398
|
+
const wantsEvent = (kind) => !eventTypes || eventTypes.includes(kind);
|
|
13399
|
+
const hasBounds = fromTimestamp !== void 0 || toTimestamp !== void 0 || fromBlock !== void 0 || toBlock !== void 0;
|
|
13400
|
+
const pageSize = hasBounds ? THE_GRAPH_MAX_BATCH_SIZE : limit;
|
|
13401
|
+
const buildPositionWhereClause = () => `where: { position: "${positionId.toLowerCase()}" }`;
|
|
13215
13402
|
const shouldQuery = {
|
|
13216
|
-
positionCreated:
|
|
13217
|
-
payment:
|
|
13218
|
-
status:
|
|
13219
|
-
liquidation:
|
|
13220
|
-
mint:
|
|
13221
|
-
withdrawal:
|
|
13222
|
-
renewal:
|
|
13223
|
-
operationFailure:
|
|
13224
|
-
mintRequest:
|
|
13225
|
-
burnRequest:
|
|
13226
|
-
collateralEvent:
|
|
13227
|
-
mintingFee:
|
|
13228
|
-
renewalFee:
|
|
13229
|
-
};
|
|
13230
|
-
const buildPositionWhereClause = () => {
|
|
13231
|
-
const conditions = [`position: "${positionId.toLowerCase()}"`];
|
|
13232
|
-
if (fromTimestamp)
|
|
13233
|
-
conditions.push(`timestamp_gte: "${fromTimestamp}"`);
|
|
13234
|
-
if (toTimestamp)
|
|
13235
|
-
conditions.push(`timestamp_lte: "${toTimestamp}"`);
|
|
13236
|
-
if (fromBlock)
|
|
13237
|
-
conditions.push(`blockNumber_gte: "${fromBlock}"`);
|
|
13238
|
-
if (toBlock)
|
|
13239
|
-
conditions.push(`blockNumber_lte: "${toBlock}"`);
|
|
13240
|
-
return `where: { ${conditions.join(", ")} }`;
|
|
13403
|
+
positionCreated: true,
|
|
13404
|
+
payment: true,
|
|
13405
|
+
status: true,
|
|
13406
|
+
liquidation: true,
|
|
13407
|
+
mint: true,
|
|
13408
|
+
withdrawal: true,
|
|
13409
|
+
renewal: true,
|
|
13410
|
+
operationFailure: true,
|
|
13411
|
+
mintRequest: true,
|
|
13412
|
+
burnRequest: true,
|
|
13413
|
+
collateralEvent: true,
|
|
13414
|
+
mintingFee: true,
|
|
13415
|
+
renewalFee: true
|
|
13241
13416
|
};
|
|
13242
13417
|
const query = `
|
|
13243
13418
|
query GetLoanEvents($positionId: Bytes!, $limit: Int!, $orderDirection: OrderDirection!) {
|
|
@@ -13473,11 +13648,41 @@ var DiamondHandsGraph = class {
|
|
|
13473
13648
|
`;
|
|
13474
13649
|
const variables = {
|
|
13475
13650
|
positionId: positionId.toLowerCase(),
|
|
13476
|
-
limit,
|
|
13651
|
+
limit: pageSize,
|
|
13477
13652
|
orderDirection
|
|
13478
13653
|
};
|
|
13479
13654
|
const result = await this.client.execute(query, variables);
|
|
13480
|
-
|
|
13655
|
+
if (hasBounds) {
|
|
13656
|
+
const collections = [
|
|
13657
|
+
["payments", result.position?.payments],
|
|
13658
|
+
["statusUpdates", result.position?.statusUpdates],
|
|
13659
|
+
["withdrawals", result.position?.withdrawals],
|
|
13660
|
+
["renewals", result.position?.renewals],
|
|
13661
|
+
["operationFailures", result.position?.operationFailures],
|
|
13662
|
+
["mintRequests", result.position?.mintRequests],
|
|
13663
|
+
["burnRequests", result.position?.burnRequests],
|
|
13664
|
+
["mintingFees", result.position?.mintingFees],
|
|
13665
|
+
["renewalFees", result.position?.renewalFees],
|
|
13666
|
+
["mints", result.ucdmintEvents],
|
|
13667
|
+
["collateralEvents", result.collateralEvents]
|
|
13668
|
+
];
|
|
13669
|
+
const saturated = collections.filter(([, list]) => (list?.length ?? 0) >= pageSize).map(([name]) => name);
|
|
13670
|
+
if (saturated.length > 0) {
|
|
13671
|
+
log.warn(
|
|
13672
|
+
"[DiamondHandsGraph] bounded getLoanEvents page saturated \u2014 the filtered history may be incomplete",
|
|
13673
|
+
{ positionId, pageSize, saturated }
|
|
13674
|
+
);
|
|
13675
|
+
}
|
|
13676
|
+
}
|
|
13677
|
+
const assembled = this.assembleLoanEvents(positionId, result);
|
|
13678
|
+
return applyLoanEventsFilter(assembled, {
|
|
13679
|
+
wantsEvent,
|
|
13680
|
+
fromTimestamp,
|
|
13681
|
+
toTimestamp,
|
|
13682
|
+
fromBlock,
|
|
13683
|
+
toBlock,
|
|
13684
|
+
limit
|
|
13685
|
+
});
|
|
13481
13686
|
}
|
|
13482
13687
|
/**
|
|
13483
13688
|
* Map one position's raw event payload into `LoanEvents`.
|
|
@@ -20560,8 +20765,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20560
20765
|
throw new Error(`Position not found: ${request.positionId}`);
|
|
20561
20766
|
}
|
|
20562
20767
|
const currentDebt = position.ucdDebt.toString();
|
|
20563
|
-
const ucdDebtHash =
|
|
20564
|
-
const contractHash =
|
|
20768
|
+
const ucdDebtHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
|
|
20769
|
+
const contractHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(
|
|
20565
20770
|
["address", "address", "address", "address"],
|
|
20566
20771
|
[
|
|
20567
20772
|
positionManagerAddress,
|
|
@@ -20638,7 +20843,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20638
20843
|
const currentPosition = await positionCore["getPositionDetails"](
|
|
20639
20844
|
positionIdBytes32
|
|
20640
20845
|
);
|
|
20641
|
-
const currentDebtHash =
|
|
20846
|
+
const currentDebtHash = keccak2565(
|
|
20642
20847
|
AbiCoder2.defaultAbiCoder().encode(
|
|
20643
20848
|
["uint256"],
|
|
20644
20849
|
[currentPosition.ucdDebt]
|
|
@@ -24550,7 +24755,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24550
24755
|
targetAddress: spend.targetAddress,
|
|
24551
24756
|
targetAmount: Number(spend.targetAmount),
|
|
24552
24757
|
authorizedAt: Number(spend.authorizedAt),
|
|
24553
|
-
utxoKey:
|
|
24758
|
+
utxoKey: solidityPackedKeccak2564(
|
|
24554
24759
|
["string", "uint32"],
|
|
24555
24760
|
[spend.txid, Number(spend.vout)]
|
|
24556
24761
|
)
|
|
@@ -25558,9 +25763,9 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25558
25763
|
to: registryAddress,
|
|
25559
25764
|
data: iface.encodeFunctionData("getLoanGrant", [pid])
|
|
25560
25765
|
});
|
|
25561
|
-
if (
|
|
25766
|
+
if (getBytes4(data).length < 96) {
|
|
25562
25767
|
throw new SDKError({
|
|
25563
|
-
message: `AgentDelegationRegistry at ${registryAddress} returned ${
|
|
25768
|
+
message: `AgentDelegationRegistry at ${registryAddress} returned ${getBytes4(data).length} bytes for getLoanGrant(bytes32) \u2014 expected at least 96. Wrong address, or a registry version this SDK does not support.`,
|
|
25564
25769
|
category: "CONTRACT" /* CONTRACT */,
|
|
25565
25770
|
severity: "HIGH" /* HIGH */
|
|
25566
25771
|
});
|
|
@@ -25569,7 +25774,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25569
25774
|
"getLoanGrant",
|
|
25570
25775
|
data
|
|
25571
25776
|
);
|
|
25572
|
-
const raw =
|
|
25777
|
+
const raw = getBytes4(data);
|
|
25573
25778
|
const withdrawScopeSupported = raw.length >= 128;
|
|
25574
25779
|
const minWithdrawRatioBps = withdrawScopeSupported ? Number(
|
|
25575
25780
|
AbiCoder2.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
|
|
@@ -26758,8 +26963,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26758
26963
|
const MIN_REVEAL_DELAY = 60;
|
|
26759
26964
|
const MAX_RANDOM_DELAY = 240;
|
|
26760
26965
|
const entropyInput = positionId + quantumTimestamp.toString();
|
|
26761
|
-
const hash =
|
|
26762
|
-
|
|
26966
|
+
const hash = keccak2565(
|
|
26967
|
+
toUtf8Bytes5(entropyInput)
|
|
26763
26968
|
);
|
|
26764
26969
|
const randomValue = BigInt(hash);
|
|
26765
26970
|
const randomDelay = Number(randomValue % BigInt(MAX_RANDOM_DELAY));
|
|
@@ -26784,12 +26989,12 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26784
26989
|
const rawPositionId = /^0x/i.test(params.positionId.trim()) ? params.positionId.trim().slice(2) : params.positionId.trim();
|
|
26785
26990
|
const canonicalPositionId = "0x" + rawPositionId.padStart(64, "0").toLowerCase();
|
|
26786
26991
|
const intentTimestamp = Math.floor(Date.now() / 1e3);
|
|
26787
|
-
const intentActionHash =
|
|
26788
|
-
const intentHash =
|
|
26992
|
+
const intentActionHash = keccak2565(toUtf8Bytes5("liquidate-position"));
|
|
26993
|
+
const intentHash = solidityPackedKeccak2564(
|
|
26789
26994
|
["bytes32", "uint256", "uint256", "address", "bytes32"],
|
|
26790
26995
|
[canonicalPositionId, intentTimestamp, chainId, intentSigner, intentActionHash]
|
|
26791
26996
|
);
|
|
26792
|
-
const intentSignature = await signer.signMessage(
|
|
26997
|
+
const intentSignature = await signer.signMessage(getBytes4(intentHash));
|
|
26793
26998
|
const response = await fetch(endpoint, {
|
|
26794
26999
|
method: "POST",
|
|
26795
27000
|
headers: { "Content-Type": "application/json" },
|
|
@@ -26841,7 +27046,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26841
27046
|
const vrfSeedRaw = await lmResult.value["vrfSeeds"](positionId);
|
|
26842
27047
|
const vrfSeed = BigInt(vrfSeedRaw.toString());
|
|
26843
27048
|
if (vrfSeed !== 0n) {
|
|
26844
|
-
const finalEntropy =
|
|
27049
|
+
const finalEntropy = solidityPackedKeccak2564(
|
|
26845
27050
|
["uint256", "uint256", "bytes32"],
|
|
26846
27051
|
[vrfSeed, BigInt(quantumTimestamp.toString()), positionId]
|
|
26847
27052
|
);
|