@bsv/wallet-toolbox 1.6.41 → 1.6.43

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/wallet-toolbox",
3
- "version": "1.6.41",
3
+ "version": "1.6.43",
4
4
  "description": "BRC100 conforming wallet, wallet storage and wallet signer components",
5
5
  "main": "./out/src/index.js",
6
6
  "types": "./out/src/index.d.ts",
@@ -574,7 +574,7 @@ export class WalletPermissionsManager implements WalletInterface {
574
574
  // brand-new permission token
575
575
  await this.createPermissionOnChain(
576
576
  request,
577
- params.expiry || Math.floor(Date.now() / 1000) + 3600 * 24 * 30, // default 30-day expiry
577
+ params.expiry || 0, // default: never expires
578
578
  params.amount
579
579
  )
580
580
  } else {
@@ -582,7 +582,7 @@ export class WalletPermissionsManager implements WalletInterface {
582
582
  await this.renewPermissionOnChain(
583
583
  request.previousToken!,
584
584
  request,
585
- params.expiry || Math.floor(Date.now() / 1000) + 3600 * 24 * 30,
585
+ params.expiry || 0, // default: never expires
586
586
  params.amount
587
587
  )
588
588
  }
@@ -591,7 +591,7 @@ export class WalletPermissionsManager implements WalletInterface {
591
591
  // Only cache non-ephemeral permissions
592
592
  // Ephemeral permissions should not be cached as they are one-time authorizations
593
593
  if (!params.ephemeral) {
594
- const expiry = params.expiry || Math.floor(Date.now() / 1000) + 3600 * 24 * 30
594
+ const expiry = params.expiry || 0 // default: never expires
595
595
  const key = this.buildRequestKey(matching.request as PermissionRequest)
596
596
  this.cachePermission(key, expiry)
597
597
  this.markRecentGrant(matching.request as PermissionRequest)
@@ -666,7 +666,7 @@ export class WalletPermissionsManager implements WalletInterface {
666
666
  }
667
667
  // --- End Validation ---
668
668
 
669
- const expiry = params.expiry || Math.floor(Date.now() / 1000) + 3600 * 24 * 30 // 30-day default
669
+ const expiry = params.expiry || 0 // default: never expires
670
670
 
671
671
  if (params.granted.spendingAuthorization) {
672
672
  await this.createPermissionOnChain(
@@ -1789,11 +1789,17 @@ export class WalletPermissionsManager implements WalletInterface {
1789
1789
  ): Promise<string> {
1790
1790
  if (!oldTokens?.length) throw new Error('No permission tokens to coalesce')
1791
1791
  if (oldTokens.length < 2) throw new Error('Need at least 2 tokens to coalesce')
1792
-
1793
1792
  // 1) Create a signable action with N inputs and a single renewed output
1793
+ // Merge all input token BEEFs into a single BEEF structure
1794
+ const inputBeef = new Beef()
1795
+ for (const token of oldTokens) {
1796
+ inputBeef.mergeBeef(Beef.fromBinary(token.tx))
1797
+ }
1798
+
1794
1799
  const { signableTransaction } = await this.createAction(
1795
1800
  {
1796
1801
  description: opts?.description ?? `Coalesce ${oldTokens.length} permission tokens`,
1802
+ inputBEEF: inputBeef.toBinary(),
1797
1803
  inputs: oldTokens.map((t, i) => ({
1798
1804
  outpoint: `${t.txid}.${t.outputIndex}`,
1799
1805
  unlockingScriptLength: 74,
@@ -1821,14 +1827,23 @@ export class WalletPermissionsManager implements WalletInterface {
1821
1827
  throw new Error('Failed to create signable transaction')
1822
1828
  }
1823
1829
 
1824
- // 2) Sign each input
1830
+ // 2) Sign each input - each token needs its own unlocker with the correct locking script
1825
1831
  const partialTx = Transaction.fromAtomicBEEF(signableTransaction.tx)
1826
1832
  const pushdrop = new PushDrop(this.underlying)
1827
- const unlocker = pushdrop.unlock(WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL, '1', 'self')
1828
1833
 
1829
1834
  const spends: Record<number, { unlockingScript: string }> = {}
1830
1835
  for (let i = 0; i < oldTokens.length; i++) {
1831
- // The signable transaction already contains the necessary prevout context
1836
+ const token = oldTokens[i]
1837
+ // Each token requires its own unlocker with the specific locking script
1838
+ const unlocker = pushdrop.unlock(
1839
+ WalletPermissionsManager.PERM_TOKEN_ENCRYPTION_PROTOCOL,
1840
+ '1',
1841
+ 'self',
1842
+ 'all',
1843
+ false,
1844
+ 1,
1845
+ LockingScript.fromHex(token.outputScript)
1846
+ )
1832
1847
  const unlockingScript = await unlocker.sign(partialTx, i)
1833
1848
  spends[i] = { unlockingScript: unlockingScript.toHex() }
1834
1849
  }
@@ -1838,7 +1853,6 @@ export class WalletPermissionsManager implements WalletInterface {
1838
1853
  reference: signableTransaction.reference,
1839
1854
  spends
1840
1855
  })
1841
-
1842
1856
  if (!txid) throw new Error('Failed to finalize coalescing transaction')
1843
1857
  return txid
1844
1858
  }
@@ -1882,7 +1896,7 @@ export class WalletPermissionsManager implements WalletInterface {
1882
1896
 
1883
1897
  // If so, coalesce them into a single token first, to avoid bloat
1884
1898
  if (oldTokens.length > 1) {
1885
- const txid = await this.coalescePermissionTokens(oldTokens, newScript, {
1899
+ await this.coalescePermissionTokens(oldTokens, newScript, {
1886
1900
  tags,
1887
1901
  basket: BASKET_MAP[r.type],
1888
1902
  description: `Coalesce ${r.type} permission tokens`
@@ -19,6 +19,7 @@ export interface WalletSettings {
19
19
  trustSettings: TrustSettings
20
20
  theme?: WalletTheme
21
21
  currency?: string
22
+ permissionMode?: string // Vendor-specific permission UX mode identifier
22
23
  }
23
24
  export interface WalletSettingsManagerConfig {
24
25
  defaultSettings: WalletSettings
@@ -47,7 +48,8 @@ export const DEFAULT_SETTINGS = {
47
48
  }
48
49
  ]
49
50
  },
50
- theme: { mode: 'dark' }
51
+ theme: { mode: 'dark' },
52
+ permissionMode: 'simple'
51
53
  } as WalletSettings
52
54
 
53
55
  // Mapping of certifier names to their testnet identity keys
@@ -56,6 +56,7 @@ export class WERR_INVALID_PARAMETER extends WalletError {
56
56
  }
57
57
  override toJson(): string {
58
58
  const obj = JSON.parse(super.toJson())
59
+ obj.code = 6 // Must match HTTPWalletJSON.ts code
59
60
  obj.parameter = this.parameter
60
61
  return JSON.stringify(obj)
61
62
  }
@@ -139,6 +140,7 @@ export class WERR_INSUFFICIENT_FUNDS extends WalletError {
139
140
  }
140
141
  override toJson(): string {
141
142
  const obj = JSON.parse(super.toJson())
143
+ obj.code = 7 // Must match HTTPWalletJSON.ts code
142
144
  obj.totalSatoshisNeeded = this.totalSatoshisNeeded
143
145
  obj.moreSatoshisNeeded = this.moreSatoshisNeeded
144
146
  return JSON.stringify(obj)
@@ -189,6 +191,7 @@ export class WERR_REVIEW_ACTIONS extends WalletError {
189
191
  }
190
192
  override toJson(): string {
191
193
  const obj = JSON.parse(super.toJson())
194
+ obj.code = 5 // Must match HTTPWalletJSON.ts code
192
195
  obj.reviewActionResults = this.reviewActionResults
193
196
  obj.sendWithResults = this.sendWithResults
194
197
  obj.txid = this.txid