@bsv/wallet-toolbox 1.1.3 → 1.1.5

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.
Files changed (54) hide show
  1. package/docs/README.md +1 -0
  2. package/docs/client.md +301 -73
  3. package/docs/setup.md +376 -69
  4. package/docs/storage.md +1 -1
  5. package/docs/wallet.md +301 -73
  6. package/license.md +28 -1
  7. package/out/src/Setup.d.ts +52 -30
  8. package/out/src/Setup.d.ts.map +1 -1
  9. package/out/src/Setup.js +26 -10
  10. package/out/src/Setup.js.map +1 -1
  11. package/out/src/SetupClient.d.ts +121 -41
  12. package/out/src/SetupClient.d.ts.map +1 -1
  13. package/out/src/SetupClient.js +138 -89
  14. package/out/src/SetupClient.js.map +1 -1
  15. package/out/src/Wallet.d.ts +10 -0
  16. package/out/src/Wallet.d.ts.map +1 -1
  17. package/out/src/Wallet.js.map +1 -1
  18. package/out/src/index.all.d.ts +1 -1
  19. package/out/src/index.all.d.ts.map +1 -1
  20. package/out/src/index.all.js +3 -2
  21. package/out/src/index.all.js.map +1 -1
  22. package/out/src/sdk/types.d.ts +5 -0
  23. package/out/src/sdk/types.d.ts.map +1 -1
  24. package/out/src/sdk/types.js.map +1 -1
  25. package/out/src/storage/WalletStorageManager.d.ts +1 -1
  26. package/out/src/storage/WalletStorageManager.js +1 -1
  27. package/out/src/storage/methods/listOutputs.d.ts.map +1 -1
  28. package/out/src/storage/methods/listOutputs.js +4 -2
  29. package/out/src/storage/methods/listOutputs.js.map +1 -1
  30. package/out/src/utility/ScriptTemplateSABPPP.d.ts +4 -0
  31. package/out/src/utility/ScriptTemplateSABPPP.d.ts.map +1 -1
  32. package/out/src/utility/ScriptTemplateSABPPP.js +4 -0
  33. package/out/src/utility/ScriptTemplateSABPPP.js.map +1 -1
  34. package/out/test/examples/README.man.test.js +8 -7
  35. package/out/test/examples/README.man.test.js.map +1 -1
  36. package/out/test/wallet/list/listOutputs.test.js +8 -12
  37. package/out/test/wallet/list/listOutputs.test.js.map +1 -1
  38. package/out/tsconfig.all.tsbuildinfo +1 -1
  39. package/package.json +1 -1
  40. package/src/Setup.ts +65 -54
  41. package/src/SetupClient.ts +241 -150
  42. package/src/Wallet.ts +10 -0
  43. package/src/index.all.ts +9 -1
  44. package/src/sdk/types.ts +7 -0
  45. package/src/storage/WalletStorageManager.ts +1 -1
  46. package/src/storage/methods/listOutputs.ts +4 -2
  47. package/src/utility/ScriptTemplateSABPPP.ts +4 -0
  48. package/test/examples/README.man.test.ts +9 -9
  49. package/test/wallet/list/listOutputs.test.ts +7 -13
  50. package/ts2md.json +0 -8
  51. package/tsconfig.all.json +1 -1
  52. package/LICENSE.txt +0 -28
  53. package/dev.sqlite3 +0 -0
  54. package/knexfile.js +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/wallet-toolbox",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
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",
package/src/Setup.ts CHANGED
@@ -1,61 +1,42 @@
1
- import {
2
- Beef,
3
- CreateActionArgs,
4
- CreateActionOutput,
5
- CreateActionResult,
6
- KeyDeriver,
7
- P2PKH,
8
- PrivateKey,
9
- PublicKey,
10
- SignActionArgs,
11
- SignActionResult,
12
- WalletInterface
13
- } from '@bsv/sdk'
1
+ import { KeyDeriver, PrivateKey } from '@bsv/sdk'
14
2
  import {
15
3
  Monitor,
16
4
  sdk,
17
5
  Services,
18
6
  SetupClient,
19
- StorageClient,
20
- verifyTruthy,
21
7
  Wallet,
22
8
  WalletStorageManager
23
9
  } from './index.client'
24
- import { PrivilegedKeyManager } from './sdk'
25
10
  import { Knex, knex as makeKnex } from 'knex'
26
- import { SetupWalletOnly, StorageKnex } from './index.all'
11
+ import { SetupWallet, SetupWalletArgs, StorageKnex } from './index.all'
27
12
 
28
13
  /**
29
- * This class provides static setup functions to construct BRC-100 compatible
14
+ * The 'Setup` class provides static setup functions to construct BRC-100 compatible
30
15
  * wallets in a variety of configurations.
31
16
  *
32
17
  * It serves as a starting point for experimentation and customization.
33
18
  *
19
+ * `SetupClient` references only browser compatible code including storage via `StorageClient`.
20
+ * `Setup` extends `SetupClient` adding database storage via `Knex` and `StorageKnex`.
21
+ *
34
22
  */
35
23
  export abstract class Setup extends SetupClient {
36
24
  /**
37
25
  * Adds `Knex` based storage to a `Wallet` configured by `Setup.createWalletOnly`
38
26
  *
39
- * @param args
40
- * @returns
27
+ * @param args.knex `Knex` object configured for either MySQL or SQLite database access.
28
+ * Schema will be created and migrated as needed.
29
+ * For MySQL, a schema corresponding to databaseName must exist with full access permissions.
30
+ * @param args.databaseName Name for this storage. For MySQL, the schema name within the MySQL instance.
31
+ * @param args.chain Which chain this wallet is on: 'main' or 'test'. Defaults to 'test'.
32
+ * @param args.rootKeyHex
33
+ *
34
+ * @publicbody
41
35
  */
42
- static async createKnexWallet(args: {
43
- /**
44
- * `Knex` object configured for either MySQL or SQLite database access.
45
- * Schema will be created and migrated as needed.
46
- * For MySQL, a schema corresponding to databaseName must exist with full access permissions.
47
- */
48
- knex: Knex<any, any[]>
49
- databaseName: string
50
- chain?: sdk.Chain
51
- rootKeyHex?: string
52
- privKeyHex?: string
53
- }): Promise<SetupWallet> {
54
- const wo = await Setup.createWalletOnly({
55
- chain: args.chain,
56
- rootKeyHex: args.rootKeyHex,
57
- privKeyHex: args.privKeyHex
58
- })
36
+ static async createKnexWallet(
37
+ args: SetupWalletKnexArgs
38
+ ): Promise<SetupWalletKnex> {
39
+ const wo = await Setup.createWallet(args)
59
40
  const activeStorage = new StorageKnex({
60
41
  chain: wo.chain,
61
42
  knex: args.knex,
@@ -68,7 +49,7 @@ export abstract class Setup extends SetupClient {
68
49
  await wo.storage.addWalletStorageProvider(activeStorage)
69
50
  const { user, isNew } = await activeStorage.findOrInsertUser(wo.identityKey)
70
51
  const userId = user.userId
71
- const r: SetupWallet = {
52
+ const r: SetupWalletKnex = {
72
53
  ...wo,
73
54
  activeStorage,
74
55
  userId
@@ -76,6 +57,9 @@ export abstract class Setup extends SetupClient {
76
57
  return r
77
58
  }
78
59
 
60
+ /**
61
+ * @publicbody
62
+ */
79
63
  static createSQLiteKnex(filename: string): Knex {
80
64
  const config: Knex.Config = {
81
65
  client: 'sqlite3',
@@ -86,6 +70,9 @@ export abstract class Setup extends SetupClient {
86
70
  return knex
87
71
  }
88
72
 
73
+ /**
74
+ * @publicbody
75
+ */
89
76
  static createMySQLKnex(connection: string, database?: string): Knex {
90
77
  const c: Knex.MySql2ConnectionConfig = JSON.parse(connection)
91
78
  if (database) {
@@ -101,26 +88,24 @@ export abstract class Setup extends SetupClient {
101
88
  return knex
102
89
  }
103
90
 
104
- static async createMySQLWallet(args: {
105
- databaseName: string
106
- chain?: sdk.Chain
107
- rootKeyHex?: string
108
- privKeyHex?: string
109
- }): Promise<SetupWallet> {
110
- const env = Setup.getEnv(args.chain || 'test')
91
+ /**
92
+ * @publicbody
93
+ */
94
+ static async createMySQLWallet(
95
+ args: SetupWalletMySQLArgs
96
+ ): Promise<SetupWalletKnex> {
111
97
  return await this.createKnexWallet({
112
98
  ...args,
113
- knex: Setup.createMySQLKnex(env.mySQLConnection, args.databaseName)
99
+ knex: Setup.createMySQLKnex(args.env.mySQLConnection, args.databaseName)
114
100
  })
115
101
  }
116
102
 
117
- static async createSQLiteWallet(args: {
118
- filePath: string
119
- databaseName: string
120
- chain?: sdk.Chain
121
- rootKeyHex?: string
122
- privKeyHex?: string
123
- }): Promise<SetupWallet> {
103
+ /**
104
+ * @publicbody
105
+ */
106
+ static async createSQLiteWallet(
107
+ args: SetupWalletSQLiteArgs
108
+ ): Promise<SetupWalletKnex> {
124
109
  return await this.createKnexWallet({
125
110
  ...args,
126
111
  knex: Setup.createSQLiteKnex(args.filePath)
@@ -128,7 +113,33 @@ export abstract class Setup extends SetupClient {
128
113
  }
129
114
  }
130
115
 
131
- export interface SetupWallet extends SetupWalletOnly {
116
+ /**
117
+ *
118
+ */
119
+ export interface SetupWalletKnexArgs extends SetupWalletArgs {
120
+ knex: Knex<any, any[]>
121
+ databaseName: string
122
+ }
123
+
124
+ /**
125
+ *
126
+ */
127
+ export interface SetupWalletMySQLArgs extends SetupWalletArgs {
128
+ databaseName: string
129
+ }
130
+
131
+ /**
132
+ *
133
+ */
134
+ export interface SetupWalletSQLiteArgs extends SetupWalletArgs {
135
+ filePath: string
136
+ databaseName: string
137
+ }
138
+
139
+ /**
140
+ *
141
+ */
142
+ export interface SetupWalletKnex extends SetupWallet {
132
143
  activeStorage: StorageKnex
133
144
  userId: number
134
145
 
@@ -1,6 +1,8 @@
1
1
  import {
2
+ BEEF,
2
3
  Beef,
3
4
  CreateActionArgs,
5
+ CreateActionOptions,
4
6
  CreateActionOutput,
5
7
  CreateActionResult,
6
8
  KeyDeriver,
@@ -9,6 +11,8 @@ import {
9
11
  PublicKey,
10
12
  SignActionArgs,
11
13
  SignActionResult,
14
+ Transaction,
15
+ UnlockingScript,
12
16
  WalletInterface
13
17
  } from '@bsv/sdk'
14
18
  import {
@@ -20,17 +24,29 @@ import {
20
24
  Wallet,
21
25
  WalletStorageManager
22
26
  } from './index.client'
23
- import { PrivilegedKeyManager } from './sdk'
24
27
 
25
28
  /**
26
- * This class provides static setup functions to construct BRC-100 compatible
29
+ * The `SetupClient` class provides static setup functions to construct BRC-100 compatible
27
30
  * wallets in a variety of configurations.
28
31
  *
29
32
  * It serves as a starting point for experimentation and customization.
30
33
  *
34
+ * `SetupClient` references only browser compatible code including storage via `StorageClient`.
35
+ * `Setup` extends `SetupClient` adding database storage via `Knex` and `StorageKnex`.
36
+ *
31
37
  */
32
38
  export abstract class SetupClient {
33
- static makeEnv(chain: sdk.Chain): void {
39
+ /**
40
+ * Creates content for .env file with some private keys, identity keys, sample API keys, and sample MySQL connection string.
41
+ *
42
+ * Two new, random private keys are generated each time, with their associated public identity keys.
43
+ *
44
+ * Loading secrets from a .env file is intended only for experimentation and getting started.
45
+ * Private keys should never be included directly in your source code.
46
+ *
47
+ * @publicBody
48
+ */
49
+ static makeEnv(): string {
34
50
  const testPrivKey1 = PrivateKey.fromRandom()
35
51
  const testIdentityKey1 = testPrivKey1.toPublicKey().toString()
36
52
  const testPrivKey2 = PrivateKey.fromRandom()
@@ -57,18 +73,24 @@ export abstract class SetupClient {
57
73
  MYSQL_CONNECTION='{"port":3306,"host":"127.0.0.1","user":"root","password":"<your_password>","database":"<your_database>", "timezone": "Z"}'
58
74
  `
59
75
  console.log(log)
76
+
77
+ return log
60
78
  }
61
79
 
62
- static getEnv(chain: sdk.Chain) {
80
+ /**
81
+ * Reads a .env file of the format created by `makeEnv`.
82
+ *
83
+ * Returns values for designated `chain`.
84
+ *
85
+ * Access private keys through the `devKeys` object: `devKeys[identityKey]`
86
+ *
87
+ * @param chain Which chain to use: 'test' or 'main'
88
+ * @returns {SetupEnv} with configuration environment secrets used by `Setup` functions.
89
+ *
90
+ * @publicBody
91
+ */
92
+ static getEnv(chain: sdk.Chain): SetupEnv {
63
93
  // Identity keys of the lead maintainer of this repo...
64
- const mainTaalApiKey = verifyTruthy(
65
- process.env.MAIN_TAAL_API_KEY || '',
66
- `.env value for 'mainTaalApiKey' is required.`
67
- )
68
- const testTaalApiKey = verifyTruthy(
69
- process.env.TEST_TAAL_API_KEY || '',
70
- `.env value for 'testTaalApiKey' is required.`
71
- )
72
94
  const identityKey =
73
95
  chain === 'main'
74
96
  ? process.env.MY_MAIN_IDENTITY
@@ -79,137 +101,39 @@ export abstract class SetupClient {
79
101
  : process.env.MY_TEST_IDENTITY2
80
102
  const DEV_KEYS = process.env.DEV_KEYS || '{}'
81
103
  const mySQLConnection = process.env.MYSQL_CONNECTION || '{}'
104
+ const taalApiKey = verifyTruthy(
105
+ chain === 'main'
106
+ ? process.env.MAIN_TAAL_API_KEY
107
+ : process.env.TEST_TAAL_API_KEY,
108
+ `.env value for '${chain.toUpperCase()}_TAAL_API_KEY' is required.`
109
+ )
110
+
111
+ if (!identityKey || !identityKey2)
112
+ throw new sdk.WERR_INVALID_OPERATION(
113
+ '.env is not a valid SetupEnv configuration.'
114
+ )
82
115
 
83
116
  return {
84
117
  chain,
85
118
  identityKey,
86
119
  identityKey2,
87
- mainTaalApiKey,
88
- testTaalApiKey,
120
+ taalApiKey,
89
121
  devKeys: JSON.parse(DEV_KEYS) as Record<string, string>,
90
122
  mySQLConnection
91
123
  }
92
124
  }
93
125
 
94
- static async createNoSendP2PKHOutpoint(
95
- basket: string,
96
- address: string,
97
- satoshis: number,
98
- noSendChange: string[] | undefined,
99
- wallet: WalletInterface
100
- ): Promise<{
101
- noSendChange: string[]
102
- txid: string
103
- cr: CreateActionResult
104
- sr: SignActionResult
105
- }> {
106
- return await SetupClient.createNoSendP2PKHOutpoints(
107
- 1,
108
- basket,
109
- address,
110
- satoshis,
111
- noSendChange,
112
- wallet
113
- )
114
- }
115
-
116
- static async createNoSendP2PKHOutpoints(
117
- count: number,
118
- basket: string,
119
- address: string,
120
- satoshis: number,
121
- noSendChange: string[] | undefined,
122
- wallet: WalletInterface
123
- ): Promise<{
124
- noSendChange: string[]
125
- txid: string
126
- cr: CreateActionResult
127
- sr: SignActionResult
128
- }> {
129
- const outputs: CreateActionOutput[] = []
130
- for (let i = 0; i < count; i++) {
131
- outputs.push({
132
- basket,
133
- satoshis,
134
- lockingScript: SetupClient.getLockP2PKH(address).toHex(),
135
- outputDescription: `p2pkh ${i}`
136
- })
137
- }
138
-
139
- const createArgs: CreateActionArgs = {
140
- description: `to ${address}`,
141
- outputs,
142
- options: {
143
- noSendChange,
144
- randomizeOutputs: false,
145
- signAndProcess: false,
146
- noSend: true
147
- }
148
- }
149
-
150
- const cr = await wallet.createAction(createArgs)
151
- noSendChange = cr.noSendChange
152
-
153
- const st = cr.signableTransaction!
154
- // const tx = Transaction.fromAtomicBEEF(st.tx) // Transaction doesn't support V2 Beef yet.
155
- const beef = Beef.fromBinary(st.tx)
156
- const btx = beef.txs.slice(-1)[0]
157
- const tx = beef.findAtomicTransaction(btx.txid)
158
-
159
- // sign and complete
160
- const signArgs: SignActionArgs = {
161
- reference: st.reference,
162
- spends: {},
163
- options: {
164
- returnTXIDOnly: true,
165
- noSend: true
166
- }
167
- }
168
-
169
- const sr = await wallet.signAction(signArgs)
170
-
171
- let txid = sr.txid!
172
- // Update the noSendChange txid to final signed value.
173
- noSendChange = noSendChange!.map(op => `${txid}.${op.split('.')[1]}`)
174
- return { noSendChange, txid, cr, sr }
175
- }
176
-
177
- static getKeyPair(priv?: string | PrivateKey): KeyPairAddress {
178
- if (priv === undefined) priv = PrivateKey.fromRandom()
179
- else if (typeof priv === 'string') priv = new PrivateKey(priv, 'hex')
180
-
181
- const pub = PublicKey.fromPrivateKey(priv)
182
- const address = pub.toAddress()
183
- return { privateKey: priv, publicKey: pub, address }
184
- }
185
-
186
- static getLockP2PKH(address: string) {
187
- const p2pkh = new P2PKH()
188
- const lock = p2pkh.lock(address)
189
- return lock
190
- }
191
-
192
- static getUnlockP2PKH(priv: PrivateKey, satoshis: number) {
193
- const p2pkh = new P2PKH()
194
- const lock = SetupClient.getLockP2PKH(SetupClient.getKeyPair(priv).address)
195
- // Prepare to pay with SIGHASH_ALL and without ANYONE_CAN_PAY.
196
- // In otherwords:
197
- // - all outputs must remain in the current order, amount and locking scripts.
198
- // - all inputs must remain from the current outpoints and sequence numbers.
199
- // (unlock scripts are never signed)
200
- const unlock = p2pkh.unlock(priv, 'all', false, satoshis, lock)
201
- return unlock
202
- }
203
-
204
- static async createWalletOnly(args: {
205
- chain?: sdk.Chain
206
- rootKeyHex?: string
207
- active?: sdk.WalletStorageProvider
208
- backups?: sdk.WalletStorageProvider[]
209
- privKeyHex?: string
210
- }): Promise<SetupWalletOnly> {
211
- args.chain ||= 'test'
212
- args.rootKeyHex ||= '1'.repeat(64)
126
+ /**
127
+ * Create a `Wallet`. Storage can optionally be provided or configured later.
128
+ *
129
+ * The following components are configured: KeyDeriver, WalletStorageManager, WalletService, WalletStorage.
130
+ * Optionally, PrivilegedKeyManager is also configured.
131
+ *
132
+ * @publicbody
133
+ */
134
+ static async createWallet(args: SetupWalletArgs): Promise<SetupWallet> {
135
+ args.chain ||= args.env.chain
136
+ args.rootKeyHex ||= args.env.devKeys[args.env.identityKey]
213
137
  const rootKey = PrivateKey.fromHex(args.rootKeyHex)
214
138
  const identityKey = rootKey.toPublicKey().toString()
215
139
  const keyDeriver = new KeyDeriver(rootKey)
@@ -220,6 +144,8 @@ export abstract class SetupClient {
220
144
  args.backups
221
145
  )
222
146
  if (storage.stores.length > 0) await storage.makeAvailable()
147
+ const serviceOptions = Services.createDefaultOptions(chain)
148
+ serviceOptions.taalApiKey = args.env.taalApiKey
223
149
  const services = new Services(args.chain)
224
150
  const monopts = Monitor.createDefaultWalletMonitorOptions(
225
151
  chain,
@@ -228,10 +154,10 @@ export abstract class SetupClient {
228
154
  )
229
155
  const monitor = new Monitor(monopts)
230
156
  monitor.addDefaultTasks()
231
- let privilegedKeyManager: PrivilegedKeyManager | undefined = undefined
157
+ let privilegedKeyManager: sdk.PrivilegedKeyManager | undefined = undefined
232
158
  if (args.privKeyHex) {
233
159
  const privKey = PrivateKey.fromString(args.privKeyHex)
234
- privilegedKeyManager = new PrivilegedKeyManager(async () => privKey)
160
+ privilegedKeyManager = new sdk.PrivilegedKeyManager(async () => privKey)
235
161
  }
236
162
  const wallet = new Wallet({
237
163
  chain,
@@ -241,7 +167,7 @@ export abstract class SetupClient {
241
167
  monitor,
242
168
  privilegedKeyManager
243
169
  })
244
- const r: SetupWalletOnly = {
170
+ const r: SetupWallet = {
245
171
  rootKey,
246
172
  identityKey,
247
173
  keyDeriver,
@@ -254,36 +180,193 @@ export abstract class SetupClient {
254
180
  return r
255
181
  }
256
182
 
257
- static async createWalletWithStorageClient(args: {
258
- rootKeyHex?: string
259
- endpointUrl?: string
260
- chain?: sdk.Chain
261
- }): Promise<SetupWalletOnly> {
262
- if (args.chain === 'main')
183
+ /**
184
+ * @publicBody
185
+ */
186
+ static async createWalletWithStorageClient(
187
+ args: SetupWalletClientArgs
188
+ ): Promise<SetupWalletClient> {
189
+ const wo = await SetupClient.createWallet(args)
190
+ if (wo.chain === 'main')
263
191
  throw new sdk.WERR_INVALID_PARAMETER(
264
192
  'chain',
265
193
  `'test' for now, 'main' is not yet supported.`
266
194
  )
267
195
 
268
- const wo = await SetupClient.createWalletOnly({
269
- chain: 'test',
270
- rootKeyHex: args.rootKeyHex
271
- })
272
- args.endpointUrl ||= 'https://staging-dojo.babbage.systems'
273
- const client = new StorageClient(wo.wallet, args.endpointUrl)
196
+ const endpointUrl =
197
+ args.endpointUrl || 'https://staging-dojo.babbage.systems'
198
+ const client = new StorageClient(wo.wallet, endpointUrl)
274
199
  await wo.storage.addWalletStorageProvider(client)
275
200
  await wo.storage.makeAvailable()
276
- return wo
201
+ return {
202
+ ...wo,
203
+ endpointUrl
204
+ }
205
+ }
206
+
207
+ /**
208
+ * @publicBody
209
+ */
210
+ static getKeyPair(priv?: string | PrivateKey): KeyPairAddress {
211
+ if (priv === undefined) priv = PrivateKey.fromRandom()
212
+ else if (typeof priv === 'string') priv = new PrivateKey(priv, 'hex')
213
+
214
+ const pub = PublicKey.fromPrivateKey(priv)
215
+ const address = pub.toAddress()
216
+ return { privateKey: priv, publicKey: pub, address }
217
+ }
218
+
219
+ /**
220
+ * @publicBody
221
+ */
222
+ static getLockP2PKH(address: string) {
223
+ const p2pkh = new P2PKH()
224
+ const lock = p2pkh.lock(address)
225
+ return lock
226
+ }
227
+
228
+ /**
229
+ * @publicBody
230
+ */
231
+ static getUnlockP2PKH(
232
+ priv: PrivateKey,
233
+ satoshis: number
234
+ ): sdk.ScriptTemplateUnlock {
235
+ const p2pkh = new P2PKH()
236
+ const lock = SetupClient.getLockP2PKH(SetupClient.getKeyPair(priv).address)
237
+ // Prepare to pay with SIGHASH_ALL and without ANYONE_CAN_PAY.
238
+ // In otherwords:
239
+ // - all outputs must remain in the current order, amount and locking scripts.
240
+ // - all inputs must remain from the current outpoints and sequence numbers.
241
+ // (unlock scripts are never signed)
242
+ const unlock = p2pkh.unlock(priv, 'all', false, satoshis, lock)
243
+ return unlock
244
+ }
245
+
246
+ /**
247
+ * @publicBody
248
+ */
249
+ static createP2PKHOutputs(
250
+ outputs: {
251
+ address: string
252
+ satoshis: number
253
+ outputDescription?: string
254
+ basket?: string
255
+ tags?: string[]
256
+ }[]
257
+ ): CreateActionOutput[] {
258
+ const os: CreateActionOutput[] = []
259
+ const count = outputs.length
260
+ for (let i = 0; i < count; i++) {
261
+ const o = outputs[i]
262
+ os.push({
263
+ basket: o.basket,
264
+ tags: o.tags,
265
+ satoshis: o.satoshis,
266
+ lockingScript: SetupClient.getLockP2PKH(o.address).toHex(),
267
+ outputDescription: o.outputDescription || `p2pkh ${i}`
268
+ })
269
+ }
270
+ return os
271
+ }
272
+
273
+ /**
274
+ * @publicBody
275
+ */
276
+ static async createP2PKHOutputsAction(
277
+ wallet: WalletInterface,
278
+ outputs: {
279
+ address: string
280
+ satoshis: number
281
+ outputDescription?: string
282
+ basket?: string
283
+ tags?: string[]
284
+ }[],
285
+ options?: CreateActionOptions
286
+ ): Promise<{
287
+ cr: CreateActionResult
288
+ outpoints: string[] | undefined
289
+ }> {
290
+ const os = SetupClient.createP2PKHOutputs(outputs)
291
+
292
+ const createArgs: CreateActionArgs = {
293
+ description: `createP2PKHOutputs`,
294
+ outputs: os,
295
+ options: {
296
+ ...options,
297
+ // Don't randomize so we can simplify outpoint creation
298
+ randomizeOutputs: false
299
+ }
300
+ }
301
+
302
+ const cr = await wallet.createAction(createArgs)
303
+
304
+ let outpoints: string[] | undefined
305
+
306
+ if (cr.txid) {
307
+ outpoints = os.map((o, i) => `${cr.txid}.${i}`)
308
+ }
309
+
310
+ return { cr, outpoints }
311
+ }
312
+
313
+ /**
314
+ * @publicBody
315
+ */
316
+ static async fundWalletFromP2PKHOutpoints(
317
+ wallet: WalletInterface,
318
+ outpoints: string[],
319
+ p2pkhKey: KeyPairAddress,
320
+ inputBEEF?: BEEF
321
+ ) {
322
+ // TODO
277
323
  }
278
324
  }
279
325
 
326
+ /**
327
+ *
328
+ */
280
329
  export type KeyPairAddress = {
281
330
  privateKey: PrivateKey
282
331
  publicKey: PublicKey
283
332
  address: string
284
333
  }
285
334
 
286
- export interface SetupWalletOnly {
335
+ /**
336
+ *
337
+ */
338
+ export interface SetupEnv {
339
+ chain: sdk.Chain
340
+ identityKey: string
341
+ identityKey2: string
342
+ taalApiKey: string
343
+ devKeys: Record<string, string>
344
+ mySQLConnection: string
345
+ }
346
+
347
+ /**
348
+ * Arguments used to construct a `Wallet`
349
+ *
350
+ * @param env Configuration "secrets" typically obtained by `Setup.makeEnv` and `Setup.getEnv` functions.
351
+ * @param chain Optional. Which chain this wallet is on: 'main' or 'test'.
352
+ * Defaults to `env.chain`.
353
+ * @param rootKeyHex Optional. The non-privileged private key used to initialize the `KeyDeriver` and determine the `identityKey`.
354
+ * Defaults to `env.devKeys[env.identityKey]
355
+ * @param privKeyHex Optional. The privileged private key used to initialize the `PrivilegedKeyManager`.
356
+ * Defaults to undefined.
357
+ * @param active. Optional. Active wallet storage. Can be added later.
358
+ * @param backups. Optional. One or more storage providers managed as backup destinations. Can be added later.
359
+ */
360
+ export interface SetupWalletArgs {
361
+ env: SetupEnv
362
+ chain?: sdk.Chain
363
+ rootKeyHex?: string
364
+ privKeyHex?: string
365
+ active?: sdk.WalletStorageProvider
366
+ backups?: sdk.WalletStorageProvider[]
367
+ }
368
+
369
+ export interface SetupWallet {
287
370
  rootKey: PrivateKey
288
371
  identityKey: string
289
372
  keyDeriver: KeyDeriver
@@ -293,3 +376,11 @@ export interface SetupWalletOnly {
293
376
  monitor: Monitor
294
377
  wallet: Wallet
295
378
  }
379
+
380
+ export interface SetupWalletClientArgs extends SetupWalletArgs {
381
+ endpointUrl?: string
382
+ }
383
+
384
+ export interface SetupWalletClient extends SetupWallet {
385
+ endpointUrl: string
386
+ }
package/src/Wallet.ts CHANGED
@@ -101,6 +101,16 @@ export class Wallet implements WalletInterface, ProtoWallet {
101
101
 
102
102
  identityKey: string
103
103
 
104
+ /**
105
+ * The wallet creates a `BeefParty` when it is created.
106
+ * All the Beefs that pass through the wallet are merged into this beef.
107
+ * Thus what it contains at any time is the union of all transactions and proof data processed.
108
+ * The class `BeefParty` derives from `Beef`, adding the ability to track the source of merged data.
109
+ *
110
+ * This allows it to generate beefs to send to a particular “party” (storage or the user)
111
+ * that includes “txid only proofs” for transactions they already know about.
112
+ * Over time, this allows an active wallet to drastically reduce the amount of data transmitted.
113
+ */
104
114
  beef: BeefParty
105
115
  trustSelf?: TrustSelf
106
116
  userParty: string