@gvnrdao/dh-sdk 0.0.336 → 0.0.338
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/dist/browser.js +1 -1
- package/dist/deployments.js +8 -8
- package/dist/deployments.mjs +8 -8
- package/dist/index.js +57 -13
- package/dist/index.mjs +57 -13
- package/dist/interfaces/chunks/config.i.d.ts +19 -0
- package/dist/safe-delegation.js +8 -8
- package/dist/safe-delegation.mjs +8 -8
- package/dist/sign-guard.d.ts +26 -0
- package/dist/sign-guard.js +1008 -0
- package/dist/sign-guard.mjs +941 -0
- package/dist/utils/borrower-authorization-712.d.ts +1 -1
- package/dist/utils/eip712-login.d.ts +34 -1
- package/dist/utils/server-session-store.d.ts +15 -0
- package/dist/utils/server-session.d.ts +13 -0
- package/dist/utils/sign-guard/errors.d.ts +9 -0
- package/dist/utils/sign-guard/extend-fee-bound.d.ts +15 -0
- package/dist/utils/sign-guard/fee-ceiling.d.ts +40 -0
- package/dist/utils/sign-guard/index.d.ts +9 -0
- package/dist/utils/sign-guard/lit-ops-client.d.ts +107 -0
- package/dist/utils/sign-guard/op-envelope.d.ts +88 -0
- package/dist/utils/sign-guard/op-specs.d.ts +51 -0
- package/dist/utils/sign-guard/sign-and-broadcast.d.ts +56 -0
- package/dist/utils/sign-guard/signable-functions.d.ts +41 -0
- package/dist/utils/sign-guard/tx-validator.d.ts +148 -0
- package/package.json +26 -4
package/dist/deployments.js
CHANGED
|
@@ -459,13 +459,13 @@ var MAINNET_DEPLOYMENT = {
|
|
|
459
459
|
block: 25472956
|
|
460
460
|
},
|
|
461
461
|
BTCSpendAuthorizer: {
|
|
462
|
-
previousImplementation: "
|
|
463
|
-
newImplementation: "
|
|
464
|
-
upgradedAt: "2026-
|
|
465
|
-
upgradedBy: "AdminModule
|
|
466
|
-
reason: "
|
|
467
|
-
executeTx: "
|
|
468
|
-
block:
|
|
462
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
463
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
464
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
465
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
466
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
467
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
468
|
+
block: 25939703
|
|
469
469
|
},
|
|
470
470
|
PositionManager: {
|
|
471
471
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -568,7 +568,7 @@ var MAINNET_DEPLOYMENT = {
|
|
|
568
568
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
569
569
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
570
570
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
571
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
571
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
572
572
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
573
573
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
574
574
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
package/dist/deployments.mjs
CHANGED
|
@@ -426,13 +426,13 @@ var MAINNET_DEPLOYMENT = {
|
|
|
426
426
|
block: 25472956
|
|
427
427
|
},
|
|
428
428
|
BTCSpendAuthorizer: {
|
|
429
|
-
previousImplementation: "
|
|
430
|
-
newImplementation: "
|
|
431
|
-
upgradedAt: "2026-
|
|
432
|
-
upgradedBy: "AdminModule
|
|
433
|
-
reason: "
|
|
434
|
-
executeTx: "
|
|
435
|
-
block:
|
|
429
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
430
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
431
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
432
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
433
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
434
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
435
|
+
block: 25939703
|
|
436
436
|
},
|
|
437
437
|
PositionManager: {
|
|
438
438
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -535,7 +535,7 @@ var MAINNET_DEPLOYMENT = {
|
|
|
535
535
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
536
536
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
537
537
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
538
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
538
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
539
539
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
540
540
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
541
541
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
package/dist/index.js
CHANGED
|
@@ -484,13 +484,13 @@ var init_deployment_addresses = __esm({
|
|
|
484
484
|
block: 25472956
|
|
485
485
|
},
|
|
486
486
|
BTCSpendAuthorizer: {
|
|
487
|
-
previousImplementation: "
|
|
488
|
-
newImplementation: "
|
|
489
|
-
upgradedAt: "2026-
|
|
490
|
-
upgradedBy: "AdminModule
|
|
491
|
-
reason: "
|
|
492
|
-
executeTx: "
|
|
493
|
-
block:
|
|
487
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
488
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
489
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
490
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
491
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
492
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
493
|
+
block: 25939703
|
|
494
494
|
},
|
|
495
495
|
PositionManager: {
|
|
496
496
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -593,7 +593,7 @@ var init_deployment_addresses = __esm({
|
|
|
593
593
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
594
594
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
595
595
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
596
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
596
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
597
597
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
598
598
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
599
599
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
@@ -5573,7 +5573,17 @@ function getSepoliaConfig() {
|
|
|
5573
5573
|
function getMainnetConfig() {
|
|
5574
5574
|
return {
|
|
5575
5575
|
mode: "service",
|
|
5576
|
-
|
|
5576
|
+
// Cutover 2026-09-08: the product's own domain. `ops.gvnr.xyz` still serves the same
|
|
5577
|
+
// broker and always will — every already-installed copy of this package calls it, so
|
|
5578
|
+
// it can never be retired. This changes what NEW installs default to, nothing else.
|
|
5579
|
+
//
|
|
5580
|
+
// Safe only because the server accepts the new audience ALREADY: the SDK derives the
|
|
5581
|
+
// login audience from this endpoint (`server-session.ts` — `loginAudience ??
|
|
5582
|
+
// serviceEndpoint`) and lit-ops-server FAILS CLOSED on an unknown one. Verified live
|
|
5583
|
+
// before this edit: DH_ACCEPTED_LOGIN_AUDIENCES on the deployed revision lists
|
|
5584
|
+
// https://ops.diamondhands.credit. Publishing this ahead of that would lock out every
|
|
5585
|
+
// client that installed it.
|
|
5586
|
+
serviceEndpoint: "https://ops.diamondhands.credit",
|
|
5577
5587
|
chainId: 1,
|
|
5578
5588
|
name: "mainnet",
|
|
5579
5589
|
// No default RPC: mainnet runs in service mode (serviceEndpoint above), so
|
|
@@ -6876,9 +6886,27 @@ var LOGIN_TYPES_WITH_AUDIENCE = {
|
|
|
6876
6886
|
{ name: "audience", type: "string" }
|
|
6877
6887
|
]
|
|
6878
6888
|
};
|
|
6879
|
-
|
|
6889
|
+
var LOGIN_TYPES_WITH_STATEMENT = {
|
|
6890
|
+
DiamondHands: [
|
|
6891
|
+
{ name: "statement", type: "string" },
|
|
6892
|
+
{ name: "address", type: "address" },
|
|
6893
|
+
{ name: "issuedAt", type: "uint256" },
|
|
6894
|
+
{ name: "nonce", type: "bytes32" },
|
|
6895
|
+
{ name: "audience", type: "string" }
|
|
6896
|
+
]
|
|
6897
|
+
};
|
|
6898
|
+
var LOGIN_STATEMENT_TEMPLATE = "{host} is verifying you own this wallet. Signing proves control of the address so we can show your loans and positions. It authorizes no transaction, moves no funds, and costs no gas.";
|
|
6899
|
+
function canonicalLoginStatement(audience) {
|
|
6900
|
+
const host = /^https?:\/\/([^/?#]+)/i.exec(audience)?.[1];
|
|
6901
|
+
if (!host)
|
|
6902
|
+
return null;
|
|
6903
|
+
return LOGIN_STATEMENT_TEMPLATE.replace("{host}", host);
|
|
6904
|
+
}
|
|
6905
|
+
async function buildSignedLoginPayload(signer, chainId, audience, reuse, withStatement = false) {
|
|
6880
6906
|
const address = await signer.getAddress();
|
|
6907
|
+
const statement = withStatement && audience ? canonicalLoginStatement(audience) : null;
|
|
6881
6908
|
const message = {
|
|
6909
|
+
...statement ? { statement } : {},
|
|
6882
6910
|
address,
|
|
6883
6911
|
issuedAt: reuse?.issuedAt ?? Math.floor(Date.now() / 1e3),
|
|
6884
6912
|
nonce: reuse?.nonce ?? (0, import_ethers4.hexlify)((0, import_ethers4.randomBytes)(32)),
|
|
@@ -6886,7 +6914,7 @@ async function buildSignedLoginPayload(signer, chainId, audience, reuse) {
|
|
|
6886
6914
|
};
|
|
6887
6915
|
const signature = await signer.signTypedData(
|
|
6888
6916
|
buildLoginDomain(chainId),
|
|
6889
|
-
audience ? LOGIN_TYPES_WITH_AUDIENCE : LOGIN_TYPES,
|
|
6917
|
+
statement ? LOGIN_TYPES_WITH_STATEMENT : audience ? LOGIN_TYPES_WITH_AUDIENCE : LOGIN_TYPES,
|
|
6890
6918
|
message
|
|
6891
6919
|
);
|
|
6892
6920
|
return { chainId, message, signature };
|
|
@@ -7059,6 +7087,8 @@ var ServerSession = class {
|
|
|
7059
7087
|
signer;
|
|
7060
7088
|
serviceEndpoint;
|
|
7061
7089
|
loginAudience;
|
|
7090
|
+
/** Whether this session's login carries the human-readable statement. */
|
|
7091
|
+
withStatement;
|
|
7062
7092
|
chainId;
|
|
7063
7093
|
store;
|
|
7064
7094
|
onSignaturePrompt;
|
|
@@ -7100,6 +7130,13 @@ var ServerSession = class {
|
|
|
7100
7130
|
/\/+$/,
|
|
7101
7131
|
""
|
|
7102
7132
|
);
|
|
7133
|
+
const explicitAudience = typeof opts.loginAudience === "string" && opts.loginAudience.length > 0;
|
|
7134
|
+
this.withStatement = opts.withStatement === true && explicitAudience;
|
|
7135
|
+
if (opts.withStatement === true && !explicitAudience) {
|
|
7136
|
+
console.warn(
|
|
7137
|
+
"[dh-sdk] withStatement ignored: it requires an explicit loginAudience, since the servers rebuild the expected sentence from the audience host"
|
|
7138
|
+
);
|
|
7139
|
+
}
|
|
7103
7140
|
this.chainId = opts.chainId;
|
|
7104
7141
|
this.store = opts.persistSession === false ? null : opts.sessionStore ?? createDefaultSessionStore();
|
|
7105
7142
|
this.onSignaturePrompt = opts.onSignaturePrompt;
|
|
@@ -7353,12 +7390,16 @@ var ServerSession = class {
|
|
|
7353
7390
|
this.signer,
|
|
7354
7391
|
this.chainId,
|
|
7355
7392
|
this.loginAudience,
|
|
7356
|
-
reuse
|
|
7393
|
+
reuse,
|
|
7394
|
+
reuse ? reuse.withStatement === true : this.withStatement
|
|
7357
7395
|
);
|
|
7358
7396
|
if (storeKey && !reuse) {
|
|
7359
7397
|
store.savePending?.(storeKey, {
|
|
7360
7398
|
issuedAt: payload.message.issuedAt,
|
|
7361
|
-
nonce: payload.message.nonce
|
|
7399
|
+
nonce: payload.message.nonce,
|
|
7400
|
+
// Recorded so a resume reproduces this digest even if the
|
|
7401
|
+
// capability flag changes before the owners finish signing.
|
|
7402
|
+
withStatement: this.withStatement
|
|
7362
7403
|
});
|
|
7363
7404
|
}
|
|
7364
7405
|
session = await this.login(payload);
|
|
@@ -19699,6 +19740,9 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
19699
19740
|
signer: config.authSigner ?? config.contractSigner,
|
|
19700
19741
|
serviceEndpoint: config.serviceEndpoint,
|
|
19701
19742
|
loginAudience: config.loginAudience,
|
|
19743
|
+
// Only meaningful alongside an audience; the servers derive the expected
|
|
19744
|
+
// sentence from its host. Defaults off so Node callers are untouched.
|
|
19745
|
+
withStatement: config.loginStatement === true,
|
|
19702
19746
|
chainId: config.chainId,
|
|
19703
19747
|
persistSession: config.sessionPersistence?.enabled,
|
|
19704
19748
|
sessionStore: config.sessionPersistence?.store,
|
package/dist/index.mjs
CHANGED
|
@@ -490,13 +490,13 @@ var init_deployment_addresses = __esm({
|
|
|
490
490
|
block: 25472956
|
|
491
491
|
},
|
|
492
492
|
BTCSpendAuthorizer: {
|
|
493
|
-
previousImplementation: "
|
|
494
|
-
newImplementation: "
|
|
495
|
-
upgradedAt: "2026-
|
|
496
|
-
upgradedBy: "AdminModule
|
|
497
|
-
reason: "
|
|
498
|
-
executeTx: "
|
|
499
|
-
block:
|
|
493
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
494
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
495
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
496
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
497
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
498
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
499
|
+
block: 25939703
|
|
500
500
|
},
|
|
501
501
|
PositionManager: {
|
|
502
502
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -599,7 +599,7 @@ var init_deployment_addresses = __esm({
|
|
|
599
599
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
600
600
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
601
601
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
602
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
602
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
603
603
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
604
604
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
605
605
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
@@ -5579,7 +5579,17 @@ function getSepoliaConfig() {
|
|
|
5579
5579
|
function getMainnetConfig() {
|
|
5580
5580
|
return {
|
|
5581
5581
|
mode: "service",
|
|
5582
|
-
|
|
5582
|
+
// Cutover 2026-09-08: the product's own domain. `ops.gvnr.xyz` still serves the same
|
|
5583
|
+
// broker and always will — every already-installed copy of this package calls it, so
|
|
5584
|
+
// it can never be retired. This changes what NEW installs default to, nothing else.
|
|
5585
|
+
//
|
|
5586
|
+
// Safe only because the server accepts the new audience ALREADY: the SDK derives the
|
|
5587
|
+
// login audience from this endpoint (`server-session.ts` — `loginAudience ??
|
|
5588
|
+
// serviceEndpoint`) and lit-ops-server FAILS CLOSED on an unknown one. Verified live
|
|
5589
|
+
// before this edit: DH_ACCEPTED_LOGIN_AUDIENCES on the deployed revision lists
|
|
5590
|
+
// https://ops.diamondhands.credit. Publishing this ahead of that would lock out every
|
|
5591
|
+
// client that installed it.
|
|
5592
|
+
serviceEndpoint: "https://ops.diamondhands.credit",
|
|
5583
5593
|
chainId: 1,
|
|
5584
5594
|
name: "mainnet",
|
|
5585
5595
|
// No default RPC: mainnet runs in service mode (serviceEndpoint above), so
|
|
@@ -6788,9 +6798,27 @@ var LOGIN_TYPES_WITH_AUDIENCE = {
|
|
|
6788
6798
|
{ name: "audience", type: "string" }
|
|
6789
6799
|
]
|
|
6790
6800
|
};
|
|
6791
|
-
|
|
6801
|
+
var LOGIN_TYPES_WITH_STATEMENT = {
|
|
6802
|
+
DiamondHands: [
|
|
6803
|
+
{ name: "statement", type: "string" },
|
|
6804
|
+
{ name: "address", type: "address" },
|
|
6805
|
+
{ name: "issuedAt", type: "uint256" },
|
|
6806
|
+
{ name: "nonce", type: "bytes32" },
|
|
6807
|
+
{ name: "audience", type: "string" }
|
|
6808
|
+
]
|
|
6809
|
+
};
|
|
6810
|
+
var LOGIN_STATEMENT_TEMPLATE = "{host} is verifying you own this wallet. Signing proves control of the address so we can show your loans and positions. It authorizes no transaction, moves no funds, and costs no gas.";
|
|
6811
|
+
function canonicalLoginStatement(audience) {
|
|
6812
|
+
const host = /^https?:\/\/([^/?#]+)/i.exec(audience)?.[1];
|
|
6813
|
+
if (!host)
|
|
6814
|
+
return null;
|
|
6815
|
+
return LOGIN_STATEMENT_TEMPLATE.replace("{host}", host);
|
|
6816
|
+
}
|
|
6817
|
+
async function buildSignedLoginPayload(signer, chainId, audience, reuse, withStatement = false) {
|
|
6792
6818
|
const address = await signer.getAddress();
|
|
6819
|
+
const statement = withStatement && audience ? canonicalLoginStatement(audience) : null;
|
|
6793
6820
|
const message = {
|
|
6821
|
+
...statement ? { statement } : {},
|
|
6794
6822
|
address,
|
|
6795
6823
|
issuedAt: reuse?.issuedAt ?? Math.floor(Date.now() / 1e3),
|
|
6796
6824
|
nonce: reuse?.nonce ?? hexlify(randomBytes(32)),
|
|
@@ -6798,7 +6826,7 @@ async function buildSignedLoginPayload(signer, chainId, audience, reuse) {
|
|
|
6798
6826
|
};
|
|
6799
6827
|
const signature = await signer.signTypedData(
|
|
6800
6828
|
buildLoginDomain(chainId),
|
|
6801
|
-
audience ? LOGIN_TYPES_WITH_AUDIENCE : LOGIN_TYPES,
|
|
6829
|
+
statement ? LOGIN_TYPES_WITH_STATEMENT : audience ? LOGIN_TYPES_WITH_AUDIENCE : LOGIN_TYPES,
|
|
6802
6830
|
message
|
|
6803
6831
|
);
|
|
6804
6832
|
return { chainId, message, signature };
|
|
@@ -6971,6 +6999,8 @@ var ServerSession = class {
|
|
|
6971
6999
|
signer;
|
|
6972
7000
|
serviceEndpoint;
|
|
6973
7001
|
loginAudience;
|
|
7002
|
+
/** Whether this session's login carries the human-readable statement. */
|
|
7003
|
+
withStatement;
|
|
6974
7004
|
chainId;
|
|
6975
7005
|
store;
|
|
6976
7006
|
onSignaturePrompt;
|
|
@@ -7012,6 +7042,13 @@ var ServerSession = class {
|
|
|
7012
7042
|
/\/+$/,
|
|
7013
7043
|
""
|
|
7014
7044
|
);
|
|
7045
|
+
const explicitAudience = typeof opts.loginAudience === "string" && opts.loginAudience.length > 0;
|
|
7046
|
+
this.withStatement = opts.withStatement === true && explicitAudience;
|
|
7047
|
+
if (opts.withStatement === true && !explicitAudience) {
|
|
7048
|
+
console.warn(
|
|
7049
|
+
"[dh-sdk] withStatement ignored: it requires an explicit loginAudience, since the servers rebuild the expected sentence from the audience host"
|
|
7050
|
+
);
|
|
7051
|
+
}
|
|
7015
7052
|
this.chainId = opts.chainId;
|
|
7016
7053
|
this.store = opts.persistSession === false ? null : opts.sessionStore ?? createDefaultSessionStore();
|
|
7017
7054
|
this.onSignaturePrompt = opts.onSignaturePrompt;
|
|
@@ -7265,12 +7302,16 @@ var ServerSession = class {
|
|
|
7265
7302
|
this.signer,
|
|
7266
7303
|
this.chainId,
|
|
7267
7304
|
this.loginAudience,
|
|
7268
|
-
reuse
|
|
7305
|
+
reuse,
|
|
7306
|
+
reuse ? reuse.withStatement === true : this.withStatement
|
|
7269
7307
|
);
|
|
7270
7308
|
if (storeKey && !reuse) {
|
|
7271
7309
|
store.savePending?.(storeKey, {
|
|
7272
7310
|
issuedAt: payload.message.issuedAt,
|
|
7273
|
-
nonce: payload.message.nonce
|
|
7311
|
+
nonce: payload.message.nonce,
|
|
7312
|
+
// Recorded so a resume reproduces this digest even if the
|
|
7313
|
+
// capability flag changes before the owners finish signing.
|
|
7314
|
+
withStatement: this.withStatement
|
|
7274
7315
|
});
|
|
7275
7316
|
}
|
|
7276
7317
|
session = await this.login(payload);
|
|
@@ -19625,6 +19666,9 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
19625
19666
|
signer: config.authSigner ?? config.contractSigner,
|
|
19626
19667
|
serviceEndpoint: config.serviceEndpoint,
|
|
19627
19668
|
loginAudience: config.loginAudience,
|
|
19669
|
+
// Only meaningful alongside an audience; the servers derive the expected
|
|
19670
|
+
// sentence from its host. Defaults off so Node callers are untouched.
|
|
19671
|
+
withStatement: config.loginStatement === true,
|
|
19628
19672
|
chainId: config.chainId,
|
|
19629
19673
|
persistSession: config.sessionPersistence?.enabled,
|
|
19630
19674
|
sessionStore: config.sessionPersistence?.store,
|
|
@@ -97,6 +97,25 @@ interface BaseSDKConfig {
|
|
|
97
97
|
* endpoint they call.
|
|
98
98
|
*/
|
|
99
99
|
loginAudience?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Add the human-readable `statement` to the server-session login — the sentence
|
|
102
|
+
* a wallet renders instead of four opaque fields.
|
|
103
|
+
*
|
|
104
|
+
* OFF by default, and the default is load-bearing. `statement` changes the
|
|
105
|
+
* EIP-712 digest, and lit-ops-server chooses its field set by presence alone, so
|
|
106
|
+
* a client that sends one to a server which predates it has EVERY login
|
|
107
|
+
* rejected. Node callers (CLI, MCP, cr-monitor) have no signing UI to improve
|
|
108
|
+
* and should leave it off entirely.
|
|
109
|
+
*
|
|
110
|
+
* A browser sets this from the same capability flag that gates its own login
|
|
111
|
+
* statement (`LOGIN_STATEMENT_ENABLED`, served via `/v1/init`), which is what
|
|
112
|
+
* keeps the two in step: the flag asserts the server accepts statements, and
|
|
113
|
+
* both logins believe it or neither does.
|
|
114
|
+
*
|
|
115
|
+
* Ignored without `loginAudience` — the servers rebuild the expected sentence
|
|
116
|
+
* from the audience host, so a statement they cannot rebuild is one they reject.
|
|
117
|
+
*/
|
|
118
|
+
loginStatement?: boolean;
|
|
100
119
|
/**
|
|
101
120
|
* Fires immediately before the server-session login requests a wallet
|
|
102
121
|
* signature — never on the silent re-mint paths. Lets UIs show a
|
package/dist/safe-delegation.js
CHANGED
|
@@ -425,13 +425,13 @@ var MAINNET_DEPLOYMENT = {
|
|
|
425
425
|
block: 25472956
|
|
426
426
|
},
|
|
427
427
|
BTCSpendAuthorizer: {
|
|
428
|
-
previousImplementation: "
|
|
429
|
-
newImplementation: "
|
|
430
|
-
upgradedAt: "2026-
|
|
431
|
-
upgradedBy: "AdminModule
|
|
432
|
-
reason: "
|
|
433
|
-
executeTx: "
|
|
434
|
-
block:
|
|
428
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
429
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
430
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
431
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
432
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
433
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
434
|
+
block: 25939703
|
|
435
435
|
},
|
|
436
436
|
PositionManager: {
|
|
437
437
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -534,7 +534,7 @@ var MAINNET_DEPLOYMENT = {
|
|
|
534
534
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
535
535
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
536
536
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
537
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
537
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
538
538
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
539
539
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
540
540
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
package/dist/safe-delegation.mjs
CHANGED
|
@@ -398,13 +398,13 @@ var MAINNET_DEPLOYMENT = {
|
|
|
398
398
|
block: 25472956
|
|
399
399
|
},
|
|
400
400
|
BTCSpendAuthorizer: {
|
|
401
|
-
previousImplementation: "
|
|
402
|
-
newImplementation: "
|
|
403
|
-
upgradedAt: "2026-
|
|
404
|
-
upgradedBy: "AdminModule
|
|
405
|
-
reason: "
|
|
406
|
-
executeTx: "
|
|
407
|
-
block:
|
|
401
|
+
previousImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
402
|
+
newImplementation: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
403
|
+
upgradedAt: "2026-09-09T12:05:35.000Z",
|
|
404
|
+
upgradedBy: "AdminModule generic op 0xc0214ff38bb454864a34f6482dcd03570b3fd04171c84be2c20184afb1a2e161 (bsa-1-7-0 ceremony: proposed by seat 0x3030C0414B6d95aA9d5A57269E51a347fCBaB472 2026-09-08T11:35:23Z, 3/3 seat signatures, 24h timelock); executeGenericAdminOperation sent by 0xF20986F02420EF443AE9BE5092FB8A4975cF3aA6 in tx 0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c (block 25939703)",
|
|
405
|
+
reason: "BTCSpendAuthorizer 1.6.0 -> 1.7.0: allow a full-vault sweep (targetAmount == satoshis); TargetMustLeaveFeeRoom -> TargetExceedsInputValue (PR #849; mainnet incidents 2026-09-04 and 2026-09-07). Impl deployed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f at nonce 430 from source 0a7c535a1 (contracts/src identical to main 99b335f77). Cross-ref onchain-auth/.safe-batches/mainnet-bsa-1-7-0-{propose,sign,execute}.json and docs/mainnet-bsa-1-7-0-ceremony-2026-09-08.md",
|
|
406
|
+
executeTx: "0x77cd231966c546177bd8f1a07bd4e705afd5c2dfbd110b096836401679c0c69c",
|
|
407
|
+
block: 25939703
|
|
408
408
|
},
|
|
409
409
|
PositionManager: {
|
|
410
410
|
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
@@ -507,7 +507,7 @@ var MAINNET_DEPLOYMENT = {
|
|
|
507
507
|
ADMIN_MODULE: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
508
508
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
509
509
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
510
|
-
BTC_SPEND_AUTHORIZER_IMPL: "
|
|
510
|
+
BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
|
|
511
511
|
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
512
512
|
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
513
513
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@gvnrdao/dh-sdk/sign-guard` — the client-side guard between an untrusted
|
|
3
|
+
* lit-ops-server's bytes and a borrower's key.
|
|
4
|
+
*
|
|
5
|
+
* A SUBPATH rather than a main-index re-export, on purpose:
|
|
6
|
+
*
|
|
7
|
+
* - it is consumed by the CLI (CJS, node) and the MCP (bundled) and must not
|
|
8
|
+
* drag the whole SDK or `@gvnrdao/dh-lit-actions` into either; the files
|
|
9
|
+
* under `utils/sign-guard/` import only `ethers` and three pure SDK
|
|
10
|
+
* modules, enforced by `scripts/check-sign-guard-imports.mjs`;
|
|
11
|
+
* - `TxValidationError` is exported from exactly one entry so `instanceof`
|
|
12
|
+
* cannot split across module realms;
|
|
13
|
+
* - the frontend shadows the bare `@gvnrdao/dh-sdk` specifier with an ambient
|
|
14
|
+
* module; subpaths escape the shim and get the package's own types.
|
|
15
|
+
*
|
|
16
|
+
* What is here: the signable-function whitelist and its decoder, the
|
|
17
|
+
* unsigned-tx validator with its fee ceiling, the quantum/nonce helpers, the
|
|
18
|
+
* operation-envelope stamper, the three delegated-op specs, the lit-ops
|
|
19
|
+
* transport with envelope narrowing, the validate → banner → wrap → sign →
|
|
20
|
+
* broadcast pipeline, and the H-3 extension-fee bound.
|
|
21
|
+
*
|
|
22
|
+
* What is deliberately NOT here: how a consumer prompts, prints, stores a
|
|
23
|
+
* session JWT, reads its fee-ceiling override, or floors priority fees. Those
|
|
24
|
+
* are consumer policy and stay consumer-side.
|
|
25
|
+
*/
|
|
26
|
+
export * from "./utils/sign-guard";
|