@bsv/btms-permission-module 1.0.0

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.
@@ -0,0 +1,307 @@
1
+ import { PermissionsModule } from '@bsv/wallet-toolbox-client';
2
+ import { BTMS } from '@bsv/btms';
3
+ /**
4
+ * BasicTokenModule - BTMS Permission Module
5
+ *
6
+ * SECURITY MODEL:
7
+ * This module enforces permissions when spending BTMS tokens stored in
8
+ * permissioned baskets (format: "p btms <assetId>"). It prevents unauthorized
9
+ * token transfers by requiring explicit user approval for each transaction.
10
+ *
11
+ * THREAT MODEL:
12
+ * - Malicious dApp attempts to spend tokens without user knowledge
13
+ * - Malicious dApp gets approval for one transaction, attempts to sign different transaction
14
+ * - Malicious dApp attempts to bypass authorization checks
15
+ * - Malicious dApp attempts to steal tokens via preimage manipulation
16
+ *
17
+ * SECURITY BOUNDARIES:
18
+ * 1. createAction: Extracts token details and prompts user for approval
19
+ * 2. createSignature: Verifies session authorization + preimage integrity
20
+ * 3. Session authorization: Time-limited (60s) to prevent replay attacks
21
+ * 4. Preimage verification: Ensures signed transaction matches approved transaction
22
+ *
23
+ * AUTHORIZATION FLOW:
24
+ * 1. createAction → extract token info → prompt user → grant session auth
25
+ * 2. createSignature → verify session auth → verify preimage → allow signature
26
+ *
27
+ * ISSUANCE HANDLING:
28
+ * Token issuance is auto-approved (no user prompt) because:
29
+ * - Issuance creates new tokens (doesn't spend existing ones)
30
+ * - Detected by ISSUE_MARKER in locking script or btms_issue tag
31
+ * - Short signatures (<157 bytes) are assumed to be issuance
32
+ */
33
+ export declare class BasicTokenModule implements PermissionsModule {
34
+ private readonly requestTokenAccess;
35
+ private readonly btms;
36
+ /**
37
+ * Session-based authorization tracking.
38
+ *
39
+ * SECURITY: Time-limited to prevent replay attacks. Each approval expires after 60s.
40
+ * Key: originator (dApp identifier)
41
+ * Value: timestamp of approval (milliseconds since epoch)
42
+ */
43
+ private sessionAuthorizations;
44
+ private readonly SESSION_TIMEOUT_MS;
45
+ /**
46
+ * Authorized transaction data from createAction responses.
47
+ *
48
+ * SECURITY: Stores cryptographic commitments (hashOutputs, outpoints) to verify
49
+ * that createSignature is signing the exact transaction the user approved.
50
+ * This prevents a malicious dApp from getting approval for one transaction
51
+ * and then signing a different transaction.
52
+ *
53
+ * Key: originator (dApp identifier)
54
+ * Value: authorized transaction details (reference, hashOutputs, outpoints, timestamp)
55
+ */
56
+ private authorizedTransactions;
57
+ /**
58
+ * Creates a new BasicTokenModule instance.
59
+ *
60
+ * @param requestTokenAccess - Callback to prompt user for token spending approval.
61
+ * Should return true if user approves, false if denied.
62
+ * SECURITY: This callback MUST be implemented securely to prevent UI spoofing.
63
+ * @param btms - BTMS instance for fetching token metadata via getAssetInfo
64
+ */
65
+ constructor(requestTokenAccess: (app: string, message: string) => Promise<boolean>, btms: BTMS);
66
+ /**
67
+ * Periodic cleanup of expired session authorizations.
68
+ * Runs every 30 seconds to prevent memory leaks.
69
+ */
70
+ private startSessionCleanup;
71
+ /**
72
+ * Intercepts wallet method requests for P-basket/protocol operations.
73
+ *
74
+ * SECURITY: This is the main entry point for all permission checks.
75
+ * All token spending operations MUST go through this method.
76
+ *
77
+ * @param req - Request object containing method, args, and originator
78
+ * @returns Modified args (unchanged in this implementation)
79
+ * @throws Error if authorization is denied
80
+ */
81
+ onRequest(req: {
82
+ method: string;
83
+ args: object;
84
+ originator: string;
85
+ }): Promise<{
86
+ args: object;
87
+ }>;
88
+ /**
89
+ * Transforms responses from the underlying wallet.
90
+ * For createAction: Captures signable transaction data for security verification.
91
+ */
92
+ onResponse(res: unknown, context: {
93
+ method: string;
94
+ originator: string;
95
+ }): Promise<unknown>;
96
+ /**
97
+ * Captures authorized transaction data from createAction response.
98
+ *
99
+ * SECURITY: This data is used to verify that createSignature calls are signing
100
+ * the exact transaction the user approved. Prevents transaction substitution attacks.
101
+ *
102
+ * Captured data:
103
+ * 1. reference - Transaction reference for matching
104
+ * 2. hashOutputs - BIP-143 hash of all outputs (prevents output modification)
105
+ * 3. authorizedOutpoints - Whitelist of inputs that can be signed (prevents input substitution)
106
+ * 4. timestamp - For expiry checking
107
+ *
108
+ * @param result - createAction response
109
+ * @param originator - dApp identifier
110
+ */
111
+ private captureAuthorizedTransaction;
112
+ /**
113
+ * Computes BIP-143 hashOutputs from a transaction.
114
+ *
115
+ * SECURITY: This hash commits to all transaction outputs. Any modification
116
+ * to outputs (amounts, recipients, scripts) will change this hash.
117
+ *
118
+ * @param tx - Transaction to compute hashOutputs for
119
+ * @returns Hex-encoded double-SHA256 hash of all outputs
120
+ */
121
+ private computeHashOutputs;
122
+ /**
123
+ * Handles createAction requests that involve BTMS P-baskets.
124
+ *
125
+ * SECURITY: This is the primary authorization checkpoint. User approval here
126
+ * grants session authorization for subsequent createSignature calls.
127
+ *
128
+ * ISSUANCE DETECTION: Token issuance is auto-approved because it creates new
129
+ * tokens rather than spending existing ones. Detected by:
130
+ * - ISSUE_MARKER in locking script
131
+ * - btms_issue tag in outputs
132
+ * - No inputs (issuance doesn't spend existing UTXOs)
133
+ *
134
+ * @param args - createAction arguments
135
+ * @param originator - dApp identifier
136
+ * @throws Error if user denies authorization
137
+ */
138
+ private handleCreateAction;
139
+ private enrichSpendInfoWithMetadata;
140
+ private classifyTokenAction;
141
+ /**
142
+ * Extracts comprehensive token spend information from createAction args.
143
+ *
144
+ * Parses ALL output locking scripts to get token data, and extracts
145
+ * recipient info from the action description.
146
+ */
147
+ private extractTokenSpendInfo;
148
+ /**
149
+ * Prompts user for token spend authorization with detailed information.
150
+ *
151
+ * SECURITY: The prompt data is JSON-encoded to prevent injection attacks.
152
+ * The UI component (TokenAccessPrompt) is responsible for safely rendering this data.
153
+ *
154
+ * @param originator - dApp identifier
155
+ * @param spendInfo - Parsed token spend information
156
+ * @throws Error if user denies authorization
157
+ */
158
+ private promptForTokenSpend;
159
+ /**
160
+ * Prompts user for token burn authorization (burns all inputs with no token outputs).
161
+ */
162
+ private promptForTokenBurn;
163
+ /**
164
+ * Prompts user for generic authorization when token details cannot be parsed.
165
+ *
166
+ * SECURITY: Fallback prompt when we can't extract detailed token information.
167
+ * Still requires explicit user approval.
168
+ *
169
+ * @param originator - dApp identifier
170
+ * @throws Error if user denies authorization
171
+ */
172
+ private promptForGenericAuthorization;
173
+ /**
174
+ * Handles createSignature requests for BTMS token spending.
175
+ *
176
+ * SECURITY: This is the second checkpoint. It verifies that:
177
+ * 1. Session authorization exists (granted by createAction approval)
178
+ * 2. The preimage matches the authorized transaction (prevents transaction substitution)
179
+ *
180
+ * ISSUANCE HANDLING:
181
+ * Token issuance is auto-approved via multiple detection methods:
182
+ * - Session auth from createAction (if ISSUE_MARKER or btms_issue tag detected)
183
+ * - Preimage parsing (checks for ISSUE_MARKER in scriptCode)
184
+ * - Short signatures (<157 bytes, not full BIP-143 preimages)
185
+ *
186
+ * @param args - createSignature arguments
187
+ * @param originator - dApp identifier
188
+ * @throws Error if authorization is denied or verification fails
189
+ */
190
+ private handleCreateSignature;
191
+ /**
192
+ * Verifies that a BIP-143 preimage matches the authorized transaction.
193
+ *
194
+ * SECURITY: This prevents a malicious dApp from:
195
+ * 1. Getting approval for one transaction
196
+ * 2. Signing a different transaction with different outputs or inputs
197
+ *
198
+ * BIP-143 preimage structure:
199
+ * - Version: 4 bytes
200
+ * - hashPrevouts: 32 bytes
201
+ * - hashSequence: 32 bytes
202
+ * - Outpoint (txid + vout): 36 bytes
203
+ * - scriptCode: variable (varint length + script)
204
+ * - Value: 8 bytes
205
+ * - Sequence: 4 bytes
206
+ * - hashOutputs: 32 bytes
207
+ * - Locktime: 4 bytes
208
+ * - Sighash type: 4 bytes
209
+ *
210
+ * Verification checks:
211
+ * 1. Outpoint being signed is in our authorized list
212
+ * 2. hashOutputs matches what we computed from createAction
213
+ *
214
+ * @param data - BIP-143 preimage bytes
215
+ * @param authorizedTx - Authorized transaction data from createAction
216
+ * @param _originator - dApp identifier (unused, for future logging)
217
+ * @throws Error if verification fails
218
+ */
219
+ private verifyPreimage;
220
+ /**
221
+ * Grants session authorization for an originator.
222
+ *
223
+ * SECURITY: Session authorization is time-limited (60s) to prevent replay attacks.
224
+ * After expiry, user must re-approve the transaction.
225
+ *
226
+ * @param originator - dApp identifier
227
+ */
228
+ private grantSessionAuthorization;
229
+ /**
230
+ * Checks if an originator has valid session authorization.
231
+ *
232
+ * SECURITY: Automatically expires and removes stale authorizations.
233
+ *
234
+ * @param originator - dApp identifier
235
+ * @returns true if valid session authorization exists
236
+ */
237
+ private hasSessionAuthorization;
238
+ /**
239
+ * Checks if a signature request is for token issuance by examining the BIP-143 preimage.
240
+ *
241
+ * ISSUANCE DETECTION: Parses the scriptCode from the preimage and checks for ISSUE_MARKER.
242
+ * This is needed because during issuance, createAction doesn't have P-basket outputs
243
+ * (basket is added later via internalizeAction), so handleCreateAction isn't triggered.
244
+ *
245
+ * @param preimage - BIP-143 preimage data
246
+ * @returns true if this is a token issuance signature
247
+ */
248
+ private isIssuanceFromPreimage;
249
+ /**
250
+ * Handles listActions requests that query BTMS token labels.
251
+ *
252
+ * Prompts the user when an app tries to list token transactions.
253
+ * This provides transparency about which apps are accessing token history.
254
+ *
255
+ * @param args - listActions arguments
256
+ * @param originator - dApp identifier
257
+ * @throws Error if user denies authorization
258
+ */
259
+ private handleListActions;
260
+ /**
261
+ * Handles listOutputs requests that query BTMS token baskets.
262
+ *
263
+ * Prompts the user when an app tries to list token balances/UTXOs.
264
+ * This provides transparency about which apps are accessing token data.
265
+ *
266
+ * @param args - listOutputs arguments
267
+ * @param originator - dApp identifier
268
+ * @throws Error if user denies authorization
269
+ */
270
+ private handleListOutputs;
271
+ /**
272
+ * Prompts user once per session for BTMS token access (listActions/listOutputs).
273
+ */
274
+ private promptForBTMSAccess;
275
+ /**
276
+ * Fetches metadata for a specific asset using btms.getAssetInfo.
277
+ *
278
+ * @param assetId - The asset ID to look up
279
+ * @returns Token metadata or null if not found
280
+ */
281
+ private getAssetMetadata;
282
+ /**
283
+ * Checks if the createAction is for token issuance.
284
+ *
285
+ * ISSUANCE DETECTION: Token issuance is detected by:
286
+ * 1. Output tags containing 'btms_type_issue'
287
+ * 2. Locking script contains ISSUE_MARKER in assetId field
288
+ *
289
+ * @param args - createAction arguments
290
+ * @returns true if this is a token issuance operation
291
+ */
292
+ private isTokenIssuance;
293
+ /**
294
+ * Parses a BTMS token locking script to extract token information.
295
+ *
296
+ * BTMS TOKEN STRUCTURE:
297
+ * - Field 0: assetId (or "ISSUE" for issuance)
298
+ * - Field 1: amount (as string)
299
+ * - Field 2: metadata (optional JSON string)
300
+ * - Field 3: signature (present in signed PushDrop scripts)
301
+ *
302
+ * @param lockingScriptHex - Hex-encoded locking script
303
+ * @returns Parsed token info or null if parsing fails
304
+ */
305
+ private parseTokenLockingScript;
306
+ }
307
+ //# sourceMappingURL=BasicTokenModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasicTokenModule.d.ts","sourceRoot":"","sources":["../src/BasicTokenModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAgB,MAAM,WAAW,CAAA;AAG9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoD;IACvF,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAE3B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAE3C;;;;;;;;;;OAUG;IACH,OAAO,CAAC,sBAAsB,CAAgD;IAE9E;;;;;;;OAOG;gBAED,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EACtE,IAAI,EAAE,IAAI;IAYZ;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;;;;;;;;OASG;IACG,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B7B;;;OAGG;IACG,UAAU,CACd,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAA;QACd,UAAU,EAAE,MAAM,CAAA;KACnB,GACA,OAAO,CAAC,OAAO,CAAC;IAUnB;;;;;;;;;;;;;;OAcG;YACW,4BAA4B;IAiD1C;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAsC1B;;;;;;;;;;;;;;;OAeG;YACW,kBAAkB;YA8ClB,2BAA2B;IAezC,OAAO,CAAC,mBAAmB;IAsB3B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAwJ7B;;;;;;;;;OASG;YACW,mBAAmB;IA+BjC;;OAEG;YACW,kBAAkB;IA4BhC;;;;;;;;OAQG;YACW,6BAA6B;IAe3C;;;;;;;;;;;;;;;;OAgBG;YACW,qBAAqB;IAuDnC;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,OAAO,CAAC,cAAc;IA6FtB;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAOjC;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAsB/B;;;;;;;;;OASG;IACH,OAAO,CAAC,sBAAsB;IAwD9B;;;;;;;;;OASG;YACW,iBAAiB;IAoB/B;;;;;;;;;OASG;YACW,iBAAiB;IAe/B;;OAEG;YACW,mBAAmB;IAmBjC;;;;;OAKG;YACW,gBAAgB;IAe9B;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;IAoCvB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uBAAuB;CAsDhC"}