@bsv/wallet-toolbox 1.2.31 → 1.2.33

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.2.31",
3
+ "version": "1.2.33",
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",
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "@bsv/auth-express-middleware": "^1.1.2",
34
34
  "@bsv/payment-express-middleware": "^1.0.4",
35
- "@bsv/sdk": "^1.4.15",
35
+ "@bsv/sdk": "^1.4.17",
36
36
  "express": "^4.21.2",
37
37
  "knex": "^3.1.0",
38
38
  "mysql2": "^3.12.0",
@@ -1,13 +1,4 @@
1
- import {
2
- CreateActionInput,
3
- LockingScript,
4
- PubKeyHex,
5
- PushDrop,
6
- Transaction,
7
- Utils,
8
- WalletInterface,
9
- WalletProtocol
10
- } from '@bsv/sdk'
1
+ import { LocalKVStore, PubKeyHex, WalletInterface } from '@bsv/sdk'
11
2
 
12
3
  export interface Certifier {
13
4
  name: string
@@ -33,10 +24,7 @@ export interface WalletSettingsManagerConfig {
33
24
  defaultSettings: WalletSettings
34
25
  }
35
26
 
36
- const PROTOCOL_ID: WalletProtocol = [2, 'wallet settings']
37
- const KEY_ID = '1'
38
27
  const SETTINGS_BASKET = 'wallet settings'
39
- const TOKEN_AMOUNT = 1
40
28
 
41
29
  // Defaults can be overridden as needed
42
30
  export const DEFAULT_SETTINGS = {
@@ -44,19 +32,12 @@ export const DEFAULT_SETTINGS = {
44
32
  trustLevel: 2,
45
33
  trustedCertifiers: [
46
34
  {
47
- name: 'Babbage Trust Services',
48
- description: 'Resolves identity information for Babbage-run APIs and Bitcoin infrastructure.',
49
- iconUrl: 'https://projectbabbage.com/favicon.ico',
35
+ name: 'Metanet Trust Services',
36
+ description: 'Registry for protocols, baskets, and certificates types',
37
+ iconUrl: 'https://bsvblockchain.org/favicon.ico',
50
38
  identityKey: '03daf815fe38f83da0ad83b5bedc520aa488aef5cbc93a93c67a7fe60406cbffe8',
51
39
  trust: 4
52
40
  },
53
- {
54
- name: 'IdentiCert',
55
- description: 'Certifies legal first and last name, and photos',
56
- iconUrl: 'https://identicert.me/favicon.ico',
57
- trust: 5,
58
- identityKey: '0295bf1c7842d14babf60daf2c733956c331f9dcb2c79e41f85fd1dda6a3fa4549'
59
- },
60
41
  {
61
42
  name: 'SocialCert',
62
43
  description: 'Certifies social media handles, phone numbers and emails',
@@ -93,12 +74,16 @@ export const TESTNET_DEFAULT_SETTINGS: WalletSettings = {
93
74
  * Manages wallet settings
94
75
  */
95
76
  export class WalletSettingsManager {
77
+ kv: LocalKVStore
78
+
96
79
  constructor(
97
80
  private wallet: WalletInterface,
98
81
  private config: WalletSettingsManagerConfig = {
99
82
  defaultSettings: DEFAULT_SETTINGS
100
83
  }
101
- ) {}
84
+ ) {
85
+ this.kv = new LocalKVStore(wallet, SETTINGS_BASKET, true)
86
+ }
102
87
 
103
88
  /**
104
89
  * Returns a user's wallet settings
@@ -106,23 +91,7 @@ export class WalletSettingsManager {
106
91
  * @returns - Wallet settings object
107
92
  */
108
93
  async get(): Promise<WalletSettings> {
109
- // List outputs in the 'wallet-settings' basket
110
- // There should only be one settings token
111
- const results = await this.wallet.listOutputs({
112
- basket: SETTINGS_BASKET,
113
- include: 'locking scripts'
114
- })
115
-
116
- // Return defaults if no settings token is found
117
- if (!results.outputs.length) {
118
- return this.config.defaultSettings
119
- }
120
-
121
- const { fields } = PushDrop.decode(
122
- LockingScript.fromHex(results.outputs[results.outputs.length - 1].lockingScript!)
123
- )
124
- // Parse and return settings token
125
- return JSON.parse(Utils.toUTF8(fields[0]))
94
+ return JSON.parse((await this.kv.get('settings', JSON.stringify(this.config.defaultSettings))) as string)
126
95
  }
127
96
 
128
97
  /**
@@ -131,114 +100,13 @@ export class WalletSettingsManager {
131
100
  * @param settings - The wallet settings to be stored.
132
101
  */
133
102
  async set(settings: WalletSettings): Promise<void> {
134
- const pushdrop = new PushDrop(this.wallet)
135
-
136
- // Build the new locking script with the updated settings JSON.
137
- const lockingScript = await pushdrop.lock(
138
- [Utils.toArray(JSON.stringify(settings), 'utf8')],
139
- PROTOCOL_ID,
140
- KEY_ID,
141
- 'self'
142
- )
143
-
144
- // Consume any existing token and create a new one with the new locking script.
145
- await this.updateToken(lockingScript)
103
+ await this.kv.set('settings', JSON.stringify(settings))
146
104
  }
147
105
 
148
106
  /**
149
107
  * Deletes the user's settings token.
150
108
  */
151
109
  async delete(): Promise<void> {
152
- // Consume the token; if none exists, consumeToken simply returns.
153
- await this.updateToken()
154
- }
155
-
156
- /**
157
- * Updates a settings token. Any previous token is consumed, and if a new locking script
158
- * is provided, it replaces what (if anything) was there before.
159
- *
160
- * @param newLockingScript - Optional locking script for replacing the settings token.
161
- * @returns {Promise<boolean>} - True if operation succeeded, throws an error otherwise.
162
- */
163
- private async updateToken(newLockingScript?: LockingScript): Promise<boolean> {
164
- const pushdrop = new PushDrop(this.wallet)
165
-
166
- // 1. List the existing token UTXO(s) for the settings basket.
167
- const existingUtxos = await this.wallet.listOutputs({
168
- basket: SETTINGS_BASKET,
169
- include: 'entire transactions'
170
- })
171
-
172
- // This is the "create a new token" path — no signAction, just a new locking script.
173
- if (!existingUtxos.outputs.length) {
174
- if (!newLockingScript) {
175
- return true
176
- }
177
- await this.wallet.createAction({
178
- description: 'Create a user settings token',
179
- outputs: [
180
- {
181
- satoshis: TOKEN_AMOUNT,
182
- lockingScript: newLockingScript.toHex(),
183
- outputDescription: 'Wallet settings token',
184
- basket: SETTINGS_BASKET
185
- }
186
- ],
187
- options: {
188
- randomizeOutputs: false,
189
- acceptDelayedBroadcast: false
190
- }
191
- })
192
- return true
193
- }
194
-
195
- // 2. Prepare the token UTXO for consumption.
196
- const tokenOutput = existingUtxos.outputs[existingUtxos.outputs.length - 1]
197
- const inputToConsume: CreateActionInput = {
198
- outpoint: tokenOutput.outpoint,
199
- unlockingScriptLength: 73,
200
- inputDescription: 'Consume old wallet settings token'
201
- }
202
-
203
- // 3. Build the outputs array: if a new locking script is provided, add an output.
204
- const outputs = newLockingScript
205
- ? [
206
- {
207
- satoshis: TOKEN_AMOUNT,
208
- lockingScript: newLockingScript.toHex(),
209
- outputDescription: 'Wallet settings token',
210
- basket: SETTINGS_BASKET
211
- }
212
- ]
213
- : []
214
-
215
- // 4. Create a signable transaction action using the inputs and (optionally) outputs.
216
- const { signableTransaction } = await this.wallet.createAction({
217
- description: `${newLockingScript ? 'Update' : 'Delete'} a user settings token`,
218
- inputBEEF: existingUtxos.BEEF!,
219
- inputs: [inputToConsume], // input index 0
220
- outputs,
221
- options: {
222
- randomizeOutputs: false,
223
- acceptDelayedBroadcast: false
224
- }
225
- })
226
- const tx = Transaction.fromBEEF(signableTransaction!.tx)
227
-
228
- // 5. Build and sign the unlocking script for the token being consumed.
229
- const unlocker = pushdrop.unlock(PROTOCOL_ID, KEY_ID, 'self')
230
- const unlockingScript = await unlocker.sign(tx, 0)
231
-
232
- // 6. Sign the transaction using our unlocking script.
233
- await this.wallet.signAction({
234
- reference: signableTransaction!.reference,
235
- spends: {
236
- 0: {
237
- unlockingScript: unlockingScript.toHex()
238
- }
239
- }
240
- })
241
-
242
- return true
110
+ await this.kv.remove('settings')
243
111
  }
244
112
  }
@@ -319,7 +319,7 @@ async function confirmDoubleSpend(
319
319
  }
320
320
  }
321
321
  }
322
- ar.competingTxs = [...competingTxids].slice(-1, 24) // keep at most 24, if they were sorted by time, keep newest
322
+ ar.competingTxs = [...competingTxids].slice(-24) // keep at most 24, if they were sorted by time, keep newest
323
323
  note.competingTxs = ar.competingTxs.join(',')
324
324
  }
325
325
  req.addHistoryNote(note)