@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.
@@ -459,13 +459,13 @@ var MAINNET_DEPLOYMENT = {
459
459
  block: 25472956
460
460
  },
461
461
  BTCSpendAuthorizer: {
462
- previousImplementation: "0xb003ed89F695E8819a85513fE17260b805B3c478",
463
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
464
- upgradedAt: "2026-07-06T10:40:59.000Z",
465
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
466
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
467
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
468
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
571
+ BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
572
572
  POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
573
573
  POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
574
574
  POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
@@ -426,13 +426,13 @@ var MAINNET_DEPLOYMENT = {
426
426
  block: 25472956
427
427
  },
428
428
  BTCSpendAuthorizer: {
429
- previousImplementation: "0xb003ed89F695E8819a85513fE17260b805B3c478",
430
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
431
- upgradedAt: "2026-07-06T10:40:59.000Z",
432
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
433
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
434
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
435
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
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: "0xb003ed89F695E8819a85513fE17260b805B3c478",
488
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
489
- upgradedAt: "2026-07-06T10:40:59.000Z",
490
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
491
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
492
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
493
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
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
- serviceEndpoint: "https://ops.gvnr.xyz",
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
- async function buildSignedLoginPayload(signer, chainId, audience, reuse) {
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: "0xb003ed89F695E8819a85513fE17260b805B3c478",
494
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
495
- upgradedAt: "2026-07-06T10:40:59.000Z",
496
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
497
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
498
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
499
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
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
- serviceEndpoint: "https://ops.gvnr.xyz",
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
- async function buildSignedLoginPayload(signer, chainId, audience, reuse) {
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
@@ -425,13 +425,13 @@ var MAINNET_DEPLOYMENT = {
425
425
  block: 25472956
426
426
  },
427
427
  BTCSpendAuthorizer: {
428
- previousImplementation: "0xb003ed89F695E8819a85513fE17260b805B3c478",
429
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
430
- upgradedAt: "2026-07-06T10:40:59.000Z",
431
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
432
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
433
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
434
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
537
+ BTC_SPEND_AUTHORIZER_IMPL: "0x00D7a47798E8ff169104b748131703B78f23390C",
538
538
  POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
539
539
  POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
540
540
  POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
@@ -398,13 +398,13 @@ var MAINNET_DEPLOYMENT = {
398
398
  block: 25472956
399
399
  },
400
400
  BTCSpendAuthorizer: {
401
- previousImplementation: "0xb003ed89F695E8819a85513fE17260b805B3c478",
402
- newImplementation: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
403
- upgradedAt: "2026-07-06T10:40:59.000Z",
404
- upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281 (block 25472957)",
405
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
406
- executeTx: "0xe1b1884a7e76c7fd569522545a04e49d5128d83d27b3892cda59f143b53b5281",
407
- block: 25472957
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: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
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";