@1sat/connect 0.0.31 → 0.0.32

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 (2) hide show
  1. package/dist/index.js +339 -66
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -100080,41 +100080,6 @@ function permissionKeyToString(key) {
100080
100080
  return `spend:${key.originator}`;
100081
100081
  }
100082
100082
  }
100083
- function permissionKeysFromGroup(originator, permissions) {
100084
- const normalized = normalizeOriginator(originator);
100085
- const keys = [];
100086
- if (permissions.spendingAuthorization) {
100087
- keys.push({ type: "spending", originator: normalized });
100088
- }
100089
- for (const p of permissions.protocolPermissions ?? []) {
100090
- if (p.counterparty === "")
100091
- continue;
100092
- const level = p.protocolID[0];
100093
- const counterparty = level === 1 ? "" : p.counterparty ?? "self";
100094
- keys.push({
100095
- type: "protocol",
100096
- originator: normalized,
100097
- privileged: false,
100098
- protocolLevel: level,
100099
- protocolName: p.protocolID[1],
100100
- counterparty
100101
- });
100102
- }
100103
- for (const b of permissions.basketAccess ?? []) {
100104
- keys.push({ type: "basket", originator: normalized, basket: b.basket });
100105
- }
100106
- for (const c of permissions.certificateAccess ?? []) {
100107
- keys.push({
100108
- type: "certificate",
100109
- originator: normalized,
100110
- privileged: false,
100111
- verifier: c.verifierPublicKey,
100112
- certType: c.type,
100113
- fields: [...c.fields].sort()
100114
- });
100115
- }
100116
- return keys;
100117
- }
100118
100083
  function isExpired(expiry, now = Date.now()) {
100119
100084
  if (!expiry)
100120
100085
  return false;
@@ -100157,6 +100122,8 @@ class InMemoryPermissionStore {
100157
100122
  }
100158
100123
  // ../wallet/dist/permissions/manager.js
100159
100124
  var import_index_client = __toESM(require_index_client5(), 1);
100125
+ var IDB_TXID_PREFIX = "idb:";
100126
+
100160
100127
  class LocalWalletPermissionsManager extends import_index_client.WalletPermissionsManager {
100161
100128
  permissionStore;
100162
100129
  pendingSingle = new Map;
@@ -100173,16 +100140,6 @@ class LocalWalletPermissionsManager extends import_index_client.WalletPermission
100173
100140
  const userHandler2 = handler;
100174
100141
  const wrapped2 = async (request3) => {
100175
100142
  this.pendingGrouped.set(request3.requestID, request3);
100176
- const keys = permissionKeysFromGroup(request3.originator, request3.permissions);
100177
- if (keys.length > 0) {
100178
- const grants = await Promise.all(keys.map((k) => this.permissionStore.findGrant(k)));
100179
- const allHit = grants.length === keys.length && grants.every((g) => g != null && !isExpired(g.expiry));
100180
- if (allHit) {
100181
- await super.dismissGroupedPermission(request3.requestID);
100182
- this.pendingGrouped.delete(request3.requestID);
100183
- return;
100184
- }
100185
- }
100186
100143
  return userHandler2(request3);
100187
100144
  };
100188
100145
  return super.bindCallback(eventName, wrapped2);
@@ -100190,20 +100147,62 @@ class LocalWalletPermissionsManager extends import_index_client.WalletPermission
100190
100147
  const userHandler = handler;
100191
100148
  const wrapped = async (request3) => {
100192
100149
  this.pendingSingle.set(request3.requestID, request3);
100193
- const key = permissionKeyFromRequest(request3);
100194
- const existing = await this.permissionStore.findGrant(key);
100195
- if (existing && !isExpired(existing.expiry)) {
100196
- await super.grantPermission({
100197
- requestID: request3.requestID,
100198
- ephemeral: true
100199
- });
100200
- this.pendingSingle.delete(request3.requestID);
100201
- return;
100202
- }
100203
100150
  return userHandler(request3);
100204
100151
  };
100205
100152
  return super.bindCallback(eventName, wrapped);
100206
100153
  }
100154
+ async ensureProtocolPermission(args) {
100155
+ const counterparty = args.protocolID[0] === 1 ? "" : args.counterparty ?? "self";
100156
+ const key = {
100157
+ type: "protocol",
100158
+ originator: normalizeOriginator(args.originator),
100159
+ privileged: !!args.privileged,
100160
+ protocolLevel: args.protocolID[0],
100161
+ protocolName: args.protocolID[1],
100162
+ counterparty
100163
+ };
100164
+ if (await this.storeHit(key))
100165
+ return true;
100166
+ return super.ensureProtocolPermission(args);
100167
+ }
100168
+ async ensureBasketAccess(args) {
100169
+ const key = {
100170
+ type: "basket",
100171
+ originator: normalizeOriginator(args.originator),
100172
+ basket: args.basket
100173
+ };
100174
+ if (await this.storeHit(key))
100175
+ return true;
100176
+ return super.ensureBasketAccess(args);
100177
+ }
100178
+ async ensureCertificateAccess(args) {
100179
+ const key = {
100180
+ type: "certificate",
100181
+ originator: normalizeOriginator(args.originator),
100182
+ privileged: !!args.privileged,
100183
+ verifier: args.verifier,
100184
+ certType: args.certType,
100185
+ fields: [...args.fields].sort()
100186
+ };
100187
+ if (await this.storeHit(key))
100188
+ return true;
100189
+ return super.ensureCertificateAccess(args);
100190
+ }
100191
+ async ensureSpendingAuthorization(args) {
100192
+ const key = {
100193
+ type: "spending",
100194
+ originator: normalizeOriginator(args.originator)
100195
+ };
100196
+ const grant = await this.permissionStore.findGrant(key);
100197
+ if (grant && !isExpired(grant.expiry) && (grant.authorizedAmount ?? 0) >= args.satoshis) {
100198
+ return true;
100199
+ }
100200
+ return super.ensureSpendingAuthorization(args);
100201
+ }
100202
+ async storeHit(key) {
100203
+ const grant = await this.permissionStore.findGrant(key);
100204
+ return !!grant && !isExpired(grant.expiry);
100205
+ }
100207
100206
  async grantPermission(params) {
100208
100207
  const request3 = this.pendingSingle.get(params.requestID);
100209
100208
  if (request3) {
@@ -100214,7 +100213,9 @@ class LocalWalletPermissionsManager extends import_index_client.WalletPermission
100214
100213
  grantedAt: Date.now(),
100215
100214
  reason: request3.reason
100216
100215
  };
100217
- if (request3.type === "spending" && request3.spending?.satoshis != null) {
100216
+ if (key.type === "spending" && params.amount != null) {
100217
+ grant.authorizedAmount = params.amount;
100218
+ } else if (request3.type === "spending" && request3.spending?.satoshis != null) {
100218
100219
  grant.authorizedAmount = request3.spending.satoshis;
100219
100220
  }
100220
100221
  await this.permissionStore.putGrant(grant);
@@ -100229,21 +100230,63 @@ class LocalWalletPermissionsManager extends import_index_client.WalletPermission
100229
100230
  async grantGroupedPermission(params) {
100230
100231
  const request3 = this.pendingGrouped.get(params.requestID);
100231
100232
  if (request3) {
100232
- const normalized = normalizeOriginator(request3.originator);
100233
- const grantedKeys = permissionKeysFromGroup(normalized, params.granted);
100233
+ const originator = normalizeOriginator(request3.originator);
100234
100234
  const now = Date.now();
100235
100235
  const expiry = params.expiry ?? 0;
100236
- for (const key of grantedKeys) {
100237
- const grant = { key, expiry, grantedAt: now };
100238
- if (key.type === "spending" && params.granted.spendingAuthorization) {
100239
- grant.authorizedAmount = params.granted.spendingAuthorization.amount;
100240
- grant.reason = params.granted.spendingAuthorization.description;
100241
- }
100242
- await this.permissionStore.putGrant(grant);
100236
+ if (params.granted.spendingAuthorization) {
100237
+ await this.permissionStore.putGrant({
100238
+ key: { type: "spending", originator },
100239
+ expiry,
100240
+ grantedAt: now,
100241
+ authorizedAmount: params.granted.spendingAuthorization.amount,
100242
+ reason: params.granted.spendingAuthorization.description
100243
+ });
100244
+ }
100245
+ for (const p of params.granted.protocolPermissions ?? []) {
100246
+ if (p.counterparty === "")
100247
+ continue;
100248
+ const level = p.protocolID[0];
100249
+ const counterparty = level === 1 ? "" : p.counterparty ?? "self";
100250
+ await this.permissionStore.putGrant({
100251
+ key: {
100252
+ type: "protocol",
100253
+ originator,
100254
+ privileged: false,
100255
+ protocolLevel: level,
100256
+ protocolName: p.protocolID[1],
100257
+ counterparty
100258
+ },
100259
+ expiry,
100260
+ grantedAt: now,
100261
+ reason: p.description
100262
+ });
100263
+ }
100264
+ for (const b of params.granted.basketAccess ?? []) {
100265
+ await this.permissionStore.putGrant({
100266
+ key: { type: "basket", originator, basket: b.basket },
100267
+ expiry,
100268
+ grantedAt: now,
100269
+ reason: b.description
100270
+ });
100271
+ }
100272
+ for (const c of params.granted.certificateAccess ?? []) {
100273
+ await this.permissionStore.putGrant({
100274
+ key: {
100275
+ type: "certificate",
100276
+ originator,
100277
+ privileged: false,
100278
+ verifier: c.verifierPublicKey,
100279
+ certType: c.type,
100280
+ fields: [...c.fields].sort()
100281
+ },
100282
+ expiry,
100283
+ grantedAt: now,
100284
+ reason: c.description
100285
+ });
100243
100286
  }
100244
100287
  this.pendingGrouped.delete(params.requestID);
100245
100288
  }
100246
- return super.grantGroupedPermission(params);
100289
+ return super.dismissGroupedPermission(params.requestID);
100247
100290
  }
100248
100291
  async denyGroupedPermission(requestID) {
100249
100292
  this.pendingGrouped.delete(requestID);
@@ -100253,11 +100296,241 @@ class LocalWalletPermissionsManager extends import_index_client.WalletPermission
100253
100296
  this.pendingGrouped.delete(requestID);
100254
100297
  return super.dismissGroupedPermission(requestID);
100255
100298
  }
100299
+ async listProtocolPermissions(filter = {}) {
100300
+ const onchain = await super.listProtocolPermissions(filter);
100301
+ const idb = await this.idbTokensFor("protocol", filter.originator, (g) => {
100302
+ if (g.key.type !== "protocol")
100303
+ return false;
100304
+ if (filter.privileged !== undefined && g.key.privileged !== filter.privileged) {
100305
+ return false;
100306
+ }
100307
+ if (filter.protocolName !== undefined && g.key.protocolName !== filter.protocolName) {
100308
+ return false;
100309
+ }
100310
+ if (filter.protocolSecurityLevel !== undefined && g.key.protocolLevel !== filter.protocolSecurityLevel) {
100311
+ return false;
100312
+ }
100313
+ if (filter.counterparty !== undefined && g.key.counterparty !== filter.counterparty) {
100314
+ return false;
100315
+ }
100316
+ return true;
100317
+ });
100318
+ return mergeTokens(onchain, idb);
100319
+ }
100320
+ async listBasketAccess(params = {}) {
100321
+ const onchain = await super.listBasketAccess(params);
100322
+ const idb = await this.idbTokensFor("basket", params.originator, (g) => {
100323
+ if (g.key.type !== "basket")
100324
+ return false;
100325
+ if (params.basket !== undefined && g.key.basket !== params.basket) {
100326
+ return false;
100327
+ }
100328
+ return true;
100329
+ });
100330
+ return mergeTokens(onchain, idb);
100331
+ }
100332
+ async listSpendingAuthorizations(params) {
100333
+ const onchain = await super.listSpendingAuthorizations(params);
100334
+ const idb = await this.idbTokensFor("spending", params.originator, (g) => g.key.type === "spending");
100335
+ return mergeTokens(onchain, idb);
100336
+ }
100337
+ async listCertificateAccess(params = {}) {
100338
+ const onchain = await super.listCertificateAccess(params);
100339
+ const idb = await this.idbTokensFor("certificate", params.originator, (g) => {
100340
+ if (g.key.type !== "certificate")
100341
+ return false;
100342
+ if (params.privileged !== undefined && g.key.privileged !== params.privileged) {
100343
+ return false;
100344
+ }
100345
+ if (params.certType !== undefined && g.key.certType !== params.certType) {
100346
+ return false;
100347
+ }
100348
+ if (params.verifier !== undefined && g.key.verifier !== params.verifier) {
100349
+ return false;
100350
+ }
100351
+ return true;
100352
+ });
100353
+ return mergeTokens(onchain, idb);
100354
+ }
100355
+ async idbTokensFor(type, originator, predicate) {
100356
+ const filter = { type };
100357
+ if (originator)
100358
+ filter.originator = normalizeOriginator(originator);
100359
+ const grants = await this.permissionStore.listGrants(filter);
100360
+ return grants.filter(predicate).map(grantToToken);
100361
+ }
100256
100362
  async revokeAllForOriginator(originator) {
100257
100363
  const normalized = normalizeOriginator(originator);
100258
100364
  await this.permissionStore.deleteAllForOriginator(normalized);
100259
100365
  return super.revokeAllForOriginator(normalized);
100260
100366
  }
100367
+ async revokePermission(oldToken) {
100368
+ const idbKey = idbKeyFromToken(oldToken);
100369
+ if (idbKey) {
100370
+ await this.permissionStore.deleteGrant(idbKey);
100371
+ }
100372
+ if (oldToken.txid.startsWith(IDB_TXID_PREFIX)) {
100373
+ return;
100374
+ }
100375
+ return super.revokePermission(oldToken);
100376
+ }
100377
+ }
100378
+ function grantToToken(grant) {
100379
+ const base = {
100380
+ txid: `${IDB_TXID_PREFIX}${permissionKeyToString(grant.key)}`,
100381
+ tx: [],
100382
+ outputIndex: 0,
100383
+ outputScript: "",
100384
+ satoshis: 0,
100385
+ originator: grant.key.originator,
100386
+ expiry: grant.expiry
100387
+ };
100388
+ switch (grant.key.type) {
100389
+ case "protocol":
100390
+ base.privileged = grant.key.privileged;
100391
+ base.protocol = grant.key.protocolName;
100392
+ base.securityLevel = grant.key.protocolLevel;
100393
+ base.counterparty = grant.key.counterparty;
100394
+ break;
100395
+ case "basket":
100396
+ base.basketName = grant.key.basket;
100397
+ break;
100398
+ case "certificate":
100399
+ base.privileged = grant.key.privileged;
100400
+ base.certType = grant.key.certType;
100401
+ base.certFields = grant.key.fields;
100402
+ base.verifier = grant.key.verifier;
100403
+ break;
100404
+ case "spending":
100405
+ if (grant.authorizedAmount != null) {
100406
+ base.authorizedAmount = grant.authorizedAmount;
100407
+ }
100408
+ break;
100409
+ }
100410
+ return base;
100411
+ }
100412
+ function idbKeyFromToken(token) {
100413
+ if (token.txid.startsWith(IDB_TXID_PREFIX)) {
100414
+ return parseIdbKey(token.txid.slice(IDB_TXID_PREFIX.length));
100415
+ }
100416
+ const originator = normalizeOriginator(token.originator);
100417
+ if (token.basketName) {
100418
+ return { type: "basket", originator, basket: token.basketName };
100419
+ }
100420
+ if (token.protocol && token.securityLevel !== undefined) {
100421
+ return {
100422
+ type: "protocol",
100423
+ originator,
100424
+ privileged: !!token.privileged,
100425
+ protocolLevel: token.securityLevel,
100426
+ protocolName: token.protocol,
100427
+ counterparty: token.counterparty ?? "self"
100428
+ };
100429
+ }
100430
+ if (token.certType && token.verifier && token.certFields) {
100431
+ return {
100432
+ type: "certificate",
100433
+ originator,
100434
+ privileged: !!token.privileged,
100435
+ verifier: token.verifier,
100436
+ certType: token.certType,
100437
+ fields: [...token.certFields].sort()
100438
+ };
100439
+ }
100440
+ if (token.authorizedAmount !== undefined) {
100441
+ return { type: "spending", originator };
100442
+ }
100443
+ return null;
100444
+ }
100445
+ function parseIdbKey(serialized) {
100446
+ const idx = serialized.indexOf(":");
100447
+ if (idx < 0)
100448
+ return null;
100449
+ const tag = serialized.slice(0, idx);
100450
+ const rest = serialized.slice(idx + 1);
100451
+ if (tag === "basket") {
100452
+ const sep = rest.indexOf(":");
100453
+ if (sep < 0)
100454
+ return null;
100455
+ return {
100456
+ type: "basket",
100457
+ originator: rest.slice(0, sep),
100458
+ basket: rest.slice(sep + 1)
100459
+ };
100460
+ }
100461
+ if (tag === "spend") {
100462
+ return { type: "spending", originator: rest };
100463
+ }
100464
+ if (tag === "proto") {
100465
+ const parts = rest.split(":");
100466
+ if (parts.length < 4)
100467
+ return null;
100468
+ const [originator, privileged, levelAndName, counterparty] = parts;
100469
+ const commaIdx = levelAndName.indexOf(",");
100470
+ if (commaIdx < 0)
100471
+ return null;
100472
+ const level = Number(levelAndName.slice(0, commaIdx));
100473
+ const protocolName = levelAndName.slice(commaIdx + 1);
100474
+ return {
100475
+ type: "protocol",
100476
+ originator,
100477
+ privileged: privileged === "true",
100478
+ protocolLevel: level,
100479
+ protocolName,
100480
+ counterparty
100481
+ };
100482
+ }
100483
+ if (tag === "cert") {
100484
+ const parts = rest.split(":");
100485
+ if (parts.length < 5)
100486
+ return null;
100487
+ const [originator, privileged, verifier, certType, fieldsJoined] = parts;
100488
+ return {
100489
+ type: "certificate",
100490
+ originator,
100491
+ privileged: privileged === "true",
100492
+ verifier,
100493
+ certType,
100494
+ fields: fieldsJoined ? fieldsJoined.split("|") : []
100495
+ };
100496
+ }
100497
+ return null;
100498
+ }
100499
+ function mergeTokens(onchain, idb) {
100500
+ const seen = new Set;
100501
+ const out = [];
100502
+ for (const t of onchain) {
100503
+ const k = onchainSignature(t);
100504
+ if (k)
100505
+ seen.add(k);
100506
+ out.push(t);
100507
+ }
100508
+ for (const t of idb) {
100509
+ const k = idbSignature(t);
100510
+ if (k && seen.has(k))
100511
+ continue;
100512
+ out.push(t);
100513
+ }
100514
+ return out;
100515
+ }
100516
+ function onchainSignature(t) {
100517
+ const originator = normalizeOriginator(t.originator);
100518
+ if (t.basketName)
100519
+ return `basket:${originator}:${t.basketName}`;
100520
+ if (t.protocol && t.securityLevel !== undefined) {
100521
+ return `proto:${originator}:${!!t.privileged}:${t.securityLevel},${t.protocol}:${t.counterparty ?? "self"}`;
100522
+ }
100523
+ if (t.certType && t.verifier && t.certFields) {
100524
+ return `cert:${originator}:${!!t.privileged}:${t.verifier}:${t.certType}:${[...t.certFields].sort().join("|")}`;
100525
+ }
100526
+ if (t.authorizedAmount !== undefined)
100527
+ return `spend:${originator}`;
100528
+ return null;
100529
+ }
100530
+ function idbSignature(t) {
100531
+ if (!t.txid.startsWith(IDB_TXID_PREFIX))
100532
+ return null;
100533
+ return t.txid.slice(IDB_TXID_PREFIX.length);
100261
100534
  }
100262
100535
  // src/connectWallet.ts
100263
100536
  var LAST_PROVIDER_KEY = "cwi_last_provider";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/connect",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "description": "Connection layer for 1Sat wallet - popup flow, events, session management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,7 +28,7 @@
28
28
  ],
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
- "@1sat/wallet": "0.0.43",
31
+ "@1sat/wallet": "0.0.44",
32
32
  "@sigma-auth/better-auth-plugin": "^0.0.84",
33
33
  "better-auth": "^1.5.4",
34
34
  "eventemitter3": "^5.0.1"
@@ -40,4 +40,4 @@
40
40
  "@bsv/sdk": "^2.0.13",
41
41
  "typescript": "^5.9.3"
42
42
  }
43
- }
43
+ }