@gvnrdao/dh-sdk 0.0.331 → 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 +396 -187
- package/dist/index.mjs +420 -211
- package/dist/modules/loan/loan-query.module.d.ts +8 -0
- 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,
|
|
@@ -10181,6 +10271,10 @@ function normalizePkpId(pkpId) {
|
|
|
10181
10271
|
}
|
|
10182
10272
|
return pkpId;
|
|
10183
10273
|
}
|
|
10274
|
+
function isNormalizedChipotlePkpId(pkpId) {
|
|
10275
|
+
const rawId = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
|
|
10276
|
+
return rawId.length === 40;
|
|
10277
|
+
}
|
|
10184
10278
|
function padPkpIdForSubgraph(pkpId) {
|
|
10185
10279
|
const raw = pkpId.startsWith("0x") ? pkpId.slice(2) : pkpId;
|
|
10186
10280
|
if (raw.length === 40) {
|
|
@@ -10465,7 +10559,7 @@ var LoanQuery = class {
|
|
|
10465
10559
|
batch.map(async (loan) => {
|
|
10466
10560
|
try {
|
|
10467
10561
|
const rawId = loan.pkpId?.startsWith("0x") ? loan.pkpId.slice(2) : loan.pkpId;
|
|
10468
|
-
const isChipotlePkpId2 = typeof rawId === "string" && rawId
|
|
10562
|
+
const isChipotlePkpId2 = typeof rawId === "string" && isNormalizedChipotlePkpId(rawId);
|
|
10469
10563
|
if (isChipotlePkpId2) {
|
|
10470
10564
|
if (this.config.positionManagerCoreAddress && this.config.provider) {
|
|
10471
10565
|
const pmContract = new Contract4(
|
|
@@ -10791,7 +10885,8 @@ function createLoanQuery(config) {
|
|
|
10791
10885
|
}
|
|
10792
10886
|
|
|
10793
10887
|
// src/modules/withdrawal-address/withdrawal-address.module.ts
|
|
10794
|
-
import { keccak256 as
|
|
10888
|
+
import { keccak256 as keccak2564, toUtf8Bytes as toUtf8Bytes4, ZeroAddress as ZeroAddress2 } from "ethers";
|
|
10889
|
+
var STATIC_CALL_DIAGNOSTIC_TIMEOUT_MS = 5e3;
|
|
10795
10890
|
var WithdrawalAddressModule = class {
|
|
10796
10891
|
config;
|
|
10797
10892
|
graphClient;
|
|
@@ -10826,7 +10921,7 @@ var WithdrawalAddressModule = class {
|
|
|
10826
10921
|
}
|
|
10827
10922
|
/** keccak256 of the canonicalized address — matches the on-chain key. */
|
|
10828
10923
|
static addressHash(btcAddress) {
|
|
10829
|
-
return
|
|
10924
|
+
return keccak2564(toUtf8Bytes4(normalizeBitcoinAddress(btcAddress)));
|
|
10830
10925
|
}
|
|
10831
10926
|
/**
|
|
10832
10927
|
* Add a Bitcoin address to the caller's allowlist. It becomes usable only
|
|
@@ -10836,13 +10931,17 @@ var WithdrawalAddressModule = class {
|
|
|
10836
10931
|
const reg = this.getRegistry();
|
|
10837
10932
|
if (!reg.success)
|
|
10838
10933
|
return reg;
|
|
10934
|
+
const normalized = normalizeBitcoinAddress(btcAddress);
|
|
10839
10935
|
try {
|
|
10840
|
-
const tx = await reg.value.addAddress(
|
|
10841
|
-
normalizeBitcoinAddress(btcAddress)
|
|
10842
|
-
);
|
|
10936
|
+
const tx = await reg.value.addAddress(normalized);
|
|
10843
10937
|
return success(tx);
|
|
10844
10938
|
} catch (error) {
|
|
10845
|
-
return this.txFailure(
|
|
10939
|
+
return this.txFailure(
|
|
10940
|
+
"addAddress",
|
|
10941
|
+
error,
|
|
10942
|
+
btcAddress,
|
|
10943
|
+
await this.staticCallDiagnostic(reg.value, "addAddress", normalized)
|
|
10944
|
+
);
|
|
10846
10945
|
}
|
|
10847
10946
|
}
|
|
10848
10947
|
/** Remove a Bitcoin address from the caller's allowlist (effective immediately). */
|
|
@@ -10850,13 +10949,17 @@ var WithdrawalAddressModule = class {
|
|
|
10850
10949
|
const reg = this.getRegistry();
|
|
10851
10950
|
if (!reg.success)
|
|
10852
10951
|
return reg;
|
|
10952
|
+
const normalized = normalizeBitcoinAddress(btcAddress);
|
|
10853
10953
|
try {
|
|
10854
|
-
const tx = await reg.value.removeAddress(
|
|
10855
|
-
normalizeBitcoinAddress(btcAddress)
|
|
10856
|
-
);
|
|
10954
|
+
const tx = await reg.value.removeAddress(normalized);
|
|
10857
10955
|
return success(tx);
|
|
10858
10956
|
} catch (error) {
|
|
10859
|
-
return this.txFailure(
|
|
10957
|
+
return this.txFailure(
|
|
10958
|
+
"removeAddress",
|
|
10959
|
+
error,
|
|
10960
|
+
btcAddress,
|
|
10961
|
+
await this.staticCallDiagnostic(reg.value, "removeAddress", normalized)
|
|
10962
|
+
);
|
|
10860
10963
|
}
|
|
10861
10964
|
}
|
|
10862
10965
|
/**
|
|
@@ -10952,16 +11055,59 @@ var WithdrawalAddressModule = class {
|
|
|
10952
11055
|
}
|
|
10953
11056
|
return success(void 0);
|
|
10954
11057
|
}
|
|
10955
|
-
|
|
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) {
|
|
10956
11101
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11102
|
+
const detail = diagnostic ? `${msg} \u2014 ${diagnostic}` : msg;
|
|
10957
11103
|
return failure(
|
|
10958
11104
|
new SDKError({
|
|
10959
11105
|
code: `SDK_WITHDRAWAL_REGISTRY_${op.toUpperCase()}_FAILED`,
|
|
10960
|
-
message: `WithdrawalAddressRegistry.${op} failed: ${
|
|
11106
|
+
message: `WithdrawalAddressRegistry.${op} failed: ${detail}`,
|
|
10961
11107
|
category: "CONTRACT" /* CONTRACT */,
|
|
10962
11108
|
severity: "MEDIUM" /* MEDIUM */,
|
|
10963
11109
|
originalError: error instanceof Error ? error : new Error(String(error)),
|
|
10964
|
-
context: { op, context }
|
|
11110
|
+
context: { op, context, diagnostic }
|
|
10965
11111
|
})
|
|
10966
11112
|
);
|
|
10967
11113
|
}
|
|
@@ -12052,6 +12198,47 @@ function normalizePkpId2(pkpId) {
|
|
|
12052
12198
|
}
|
|
12053
12199
|
return pkpId;
|
|
12054
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
|
+
}
|
|
12055
12242
|
function hasLoanEventsFilter(filter) {
|
|
12056
12243
|
if (!filter)
|
|
12057
12244
|
return false;
|
|
@@ -13208,32 +13395,24 @@ var DiamondHandsGraph = class {
|
|
|
13208
13395
|
limit = 1e3,
|
|
13209
13396
|
orderDirection = "desc"
|
|
13210
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()}" }`;
|
|
13211
13402
|
const shouldQuery = {
|
|
13212
|
-
positionCreated:
|
|
13213
|
-
payment:
|
|
13214
|
-
status:
|
|
13215
|
-
liquidation:
|
|
13216
|
-
mint:
|
|
13217
|
-
withdrawal:
|
|
13218
|
-
renewal:
|
|
13219
|
-
operationFailure:
|
|
13220
|
-
mintRequest:
|
|
13221
|
-
burnRequest:
|
|
13222
|
-
collateralEvent:
|
|
13223
|
-
mintingFee:
|
|
13224
|
-
renewalFee:
|
|
13225
|
-
};
|
|
13226
|
-
const buildPositionWhereClause = () => {
|
|
13227
|
-
const conditions = [`position: "${positionId.toLowerCase()}"`];
|
|
13228
|
-
if (fromTimestamp)
|
|
13229
|
-
conditions.push(`timestamp_gte: "${fromTimestamp}"`);
|
|
13230
|
-
if (toTimestamp)
|
|
13231
|
-
conditions.push(`timestamp_lte: "${toTimestamp}"`);
|
|
13232
|
-
if (fromBlock)
|
|
13233
|
-
conditions.push(`blockNumber_gte: "${fromBlock}"`);
|
|
13234
|
-
if (toBlock)
|
|
13235
|
-
conditions.push(`blockNumber_lte: "${toBlock}"`);
|
|
13236
|
-
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
|
|
13237
13416
|
};
|
|
13238
13417
|
const query = `
|
|
13239
13418
|
query GetLoanEvents($positionId: Bytes!, $limit: Int!, $orderDirection: OrderDirection!) {
|
|
@@ -13469,11 +13648,41 @@ var DiamondHandsGraph = class {
|
|
|
13469
13648
|
`;
|
|
13470
13649
|
const variables = {
|
|
13471
13650
|
positionId: positionId.toLowerCase(),
|
|
13472
|
-
limit,
|
|
13651
|
+
limit: pageSize,
|
|
13473
13652
|
orderDirection
|
|
13474
13653
|
};
|
|
13475
13654
|
const result = await this.client.execute(query, variables);
|
|
13476
|
-
|
|
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
|
+
});
|
|
13477
13686
|
}
|
|
13478
13687
|
/**
|
|
13479
13688
|
* Map one position's raw event payload into `LoanEvents`.
|
|
@@ -20556,8 +20765,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20556
20765
|
throw new Error(`Position not found: ${request.positionId}`);
|
|
20557
20766
|
}
|
|
20558
20767
|
const currentDebt = position.ucdDebt.toString();
|
|
20559
|
-
const ucdDebtHash =
|
|
20560
|
-
const contractHash =
|
|
20768
|
+
const ucdDebtHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(["uint256"], [currentDebt]));
|
|
20769
|
+
const contractHash = keccak2565(AbiCoder2.defaultAbiCoder().encode(
|
|
20561
20770
|
["address", "address", "address", "address"],
|
|
20562
20771
|
[
|
|
20563
20772
|
positionManagerAddress,
|
|
@@ -20634,7 +20843,7 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
20634
20843
|
const currentPosition = await positionCore["getPositionDetails"](
|
|
20635
20844
|
positionIdBytes32
|
|
20636
20845
|
);
|
|
20637
|
-
const currentDebtHash =
|
|
20846
|
+
const currentDebtHash = keccak2565(
|
|
20638
20847
|
AbiCoder2.defaultAbiCoder().encode(
|
|
20639
20848
|
["uint256"],
|
|
20640
20849
|
[currentPosition.ucdDebt]
|
|
@@ -24546,7 +24755,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24546
24755
|
targetAddress: spend.targetAddress,
|
|
24547
24756
|
targetAmount: Number(spend.targetAmount),
|
|
24548
24757
|
authorizedAt: Number(spend.authorizedAt),
|
|
24549
|
-
utxoKey:
|
|
24758
|
+
utxoKey: solidityPackedKeccak2564(
|
|
24550
24759
|
["string", "uint32"],
|
|
24551
24760
|
[spend.txid, Number(spend.vout)]
|
|
24552
24761
|
)
|
|
@@ -25554,9 +25763,9 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25554
25763
|
to: registryAddress,
|
|
25555
25764
|
data: iface.encodeFunctionData("getLoanGrant", [pid])
|
|
25556
25765
|
});
|
|
25557
|
-
if (
|
|
25766
|
+
if (getBytes4(data).length < 96) {
|
|
25558
25767
|
throw new SDKError({
|
|
25559
|
-
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.`,
|
|
25560
25769
|
category: "CONTRACT" /* CONTRACT */,
|
|
25561
25770
|
severity: "HIGH" /* HIGH */
|
|
25562
25771
|
});
|
|
@@ -25565,7 +25774,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
25565
25774
|
"getLoanGrant",
|
|
25566
25775
|
data
|
|
25567
25776
|
);
|
|
25568
|
-
const raw =
|
|
25777
|
+
const raw = getBytes4(data);
|
|
25569
25778
|
const withdrawScopeSupported = raw.length >= 128;
|
|
25570
25779
|
const minWithdrawRatioBps = withdrawScopeSupported ? Number(
|
|
25571
25780
|
AbiCoder2.defaultAbiCoder().decode(["uint32"], raw.slice(96, 128))[0]
|
|
@@ -26754,8 +26963,8 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26754
26963
|
const MIN_REVEAL_DELAY = 60;
|
|
26755
26964
|
const MAX_RANDOM_DELAY = 240;
|
|
26756
26965
|
const entropyInput = positionId + quantumTimestamp.toString();
|
|
26757
|
-
const hash =
|
|
26758
|
-
|
|
26966
|
+
const hash = keccak2565(
|
|
26967
|
+
toUtf8Bytes5(entropyInput)
|
|
26759
26968
|
);
|
|
26760
26969
|
const randomValue = BigInt(hash);
|
|
26761
26970
|
const randomDelay = Number(randomValue % BigInt(MAX_RANDOM_DELAY));
|
|
@@ -26780,12 +26989,12 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26780
26989
|
const rawPositionId = /^0x/i.test(params.positionId.trim()) ? params.positionId.trim().slice(2) : params.positionId.trim();
|
|
26781
26990
|
const canonicalPositionId = "0x" + rawPositionId.padStart(64, "0").toLowerCase();
|
|
26782
26991
|
const intentTimestamp = Math.floor(Date.now() / 1e3);
|
|
26783
|
-
const intentActionHash =
|
|
26784
|
-
const intentHash =
|
|
26992
|
+
const intentActionHash = keccak2565(toUtf8Bytes5("liquidate-position"));
|
|
26993
|
+
const intentHash = solidityPackedKeccak2564(
|
|
26785
26994
|
["bytes32", "uint256", "uint256", "address", "bytes32"],
|
|
26786
26995
|
[canonicalPositionId, intentTimestamp, chainId, intentSigner, intentActionHash]
|
|
26787
26996
|
);
|
|
26788
|
-
const intentSignature = await signer.signMessage(
|
|
26997
|
+
const intentSignature = await signer.signMessage(getBytes4(intentHash));
|
|
26789
26998
|
const response = await fetch(endpoint, {
|
|
26790
26999
|
method: "POST",
|
|
26791
27000
|
headers: { "Content-Type": "application/json" },
|
|
@@ -26837,7 +27046,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
26837
27046
|
const vrfSeedRaw = await lmResult.value["vrfSeeds"](positionId);
|
|
26838
27047
|
const vrfSeed = BigInt(vrfSeedRaw.toString());
|
|
26839
27048
|
if (vrfSeed !== 0n) {
|
|
26840
|
-
const finalEntropy =
|
|
27049
|
+
const finalEntropy = solidityPackedKeccak2564(
|
|
26841
27050
|
["uint256", "uint256", "bytes32"],
|
|
26842
27051
|
[vrfSeed, BigInt(quantumTimestamp.toString()), positionId]
|
|
26843
27052
|
);
|