@1sat/wallet 0.0.40 → 0.0.42
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions/adapter.d.ts +91 -0
- package/dist/permissions/adapter.d.ts.map +1 -0
- package/dist/permissions/adapter.js +317 -0
- package/dist/permissions/adapter.js.map +1 -0
- package/dist/permissions/in-memory-store.d.ts +17 -0
- package/dist/permissions/in-memory-store.d.ts.map +1 -0
- package/dist/permissions/in-memory-store.js +42 -0
- package/dist/permissions/in-memory-store.js.map +1 -0
- package/dist/permissions/index.d.ts +6 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/key.d.ts +55 -0
- package/dist/permissions/key.d.ts.map +1 -0
- package/dist/permissions/key.js +234 -0
- package/dist/permissions/key.js.map +1 -0
- package/dist/permissions/types.d.ts +132 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +2 -0
- package/dist/permissions/types.js.map +1 -0
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export { FileBackupProvider, FileRestoreReader, Zip, ZipDeflate, unzip, type Bac
|
|
|
8
8
|
export { ChromeCWI, CWIEventName, EventCWI, createChromeCWI, createCWI, createEventCWI, createSigmaCWI, createWebCWI, type CWIResponseDetail, type CWITransport, type SigmaCWIConfig, type SigmaCWIResult, type WebCWIConfig, type WebCWIResult, } from './cwi';
|
|
9
9
|
export { parsePrivateKey } from './parsePrivateKey';
|
|
10
10
|
export { createWalletCore, DEFAULT_FEE_MODEL, DEFAULT_CONNECTION_TIMEOUT, type Chain, type WalletCoreConfig, type WalletCoreResult, } from './factory';
|
|
11
|
+
export { filterGroupedByMissing, InMemoryPermissionStore, isExpired, normalizeOriginator, PermissionLedgerAdapter, permissionKeyFromRequest, permissionKeysFromGroup, permissionKeyToString, } from './permissions';
|
|
12
|
+
export type { CounterpartyPermissionPromptDecision, GroupedPermissionPromptDecision, IPermissionStore, ListGrantsFilter, PermissionKey, PermissionLedgerAdapterOptions, PermissionPromptDecision, PermissionPromptHandler, PermissionRecord, PermissionRecordSource, PermissionType, StoredGrant, } from './permissions';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,YAAY,EACX,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,UAAU,GACV,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAGzD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,GACT,MAAM,cAAc,CAAA;AAGrB,OAAO,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,GAAG,GACR,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,KAAK,iBAAiB,GACtB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,UAAU,EACV,KAAK,EACL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,QAAQ,GACb,MAAM,UAAU,CAAA;AAGjB,OAAO,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,OAAO,CAAA;AAMd,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,KAAK,KAAK,EACV,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,YAAY,EACX,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,UAAU,GACV,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAGzD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,GACT,MAAM,cAAc,CAAA;AAGrB,OAAO,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,IAAI,EACT,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,GAAG,GACR,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,KAAK,iBAAiB,GACtB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,UAAU,EACV,KAAK,EACL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,QAAQ,GACb,MAAM,UAAU,CAAA;AAGjB,OAAO,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,OAAO,CAAA;AAMd,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,KAAK,KAAK,EACV,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACrB,MAAM,WAAW,CAAA;AAGlB,OAAO,EACN,sBAAsB,EACtB,uBAAuB,EACvB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,eAAe,CAAA;AACtB,YAAY,EACX,oCAAoC,EACpC,+BAA+B,EAC/B,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,GACX,MAAM,eAAe,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -18,4 +18,6 @@ export { ChromeCWI, CWIEventName, EventCWI, createChromeCWI, createCWI, createEv
|
|
|
18
18
|
export { parsePrivateKey } from './parsePrivateKey';
|
|
19
19
|
// Factory core
|
|
20
20
|
export { createWalletCore, DEFAULT_FEE_MODEL, DEFAULT_CONNECTION_TIMEOUT, } from './factory';
|
|
21
|
+
// Permissions (BRC-100 permission ledger + adapter)
|
|
22
|
+
export { filterGroupedByMissing, InMemoryPermissionStore, isExpired, normalizeOriginator, PermissionLedgerAdapter, permissionKeyFromRequest, permissionKeysFromGroup, permissionKeyToString, } from './permissions';
|
|
21
23
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAU7C,UAAU;AACV,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD,cAAc;AACd,OAAO,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,GACT,MAAM,cAAc,CAAA;AAErB,WAAW;AACX,OAAO,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,GAYZ,MAAM,YAAY,CAAA;AAEnB,eAAe;AACf,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,YAAY,GAEZ,MAAM,gBAAgB,CAAA;AAEvB,SAAS;AACT,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,UAAU,EACV,KAAK,GAKL,MAAM,UAAU,CAAA;AAEjB,+BAA+B;AAC/B,OAAO,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,GAOZ,MAAM,OAAO,CAAA;AAEd,8EAA8E;AAC9E,sDAAsD;AAEtD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,eAAe;AACf,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,GAI1B,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAU7C,UAAU;AACV,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD,cAAc;AACd,OAAO,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,GACT,MAAM,cAAc,CAAA;AAErB,WAAW;AACX,OAAO,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,OAAO,EACP,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,GAYZ,MAAM,YAAY,CAAA;AAEnB,eAAe;AACf,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,YAAY,GAEZ,MAAM,gBAAgB,CAAA;AAEvB,SAAS;AACT,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,UAAU,EACV,KAAK,GAKL,MAAM,UAAU,CAAA;AAEjB,+BAA+B;AAC/B,OAAO,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,YAAY,GAOZ,MAAM,OAAO,CAAA;AAEd,8EAA8E;AAC9E,sDAAsD;AAEtD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,eAAe;AACf,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,GAI1B,MAAM,WAAW,CAAA;AAElB,oDAAoD;AACpD,OAAO,EACN,sBAAsB,EACtB,uBAAuB,EACvB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { WalletPermissionsManager } from '@bsv/wallet-toolbox';
|
|
2
|
+
import type { IPermissionStore, PermissionKey, PermissionPromptHandler, PermissionRecord } from './types';
|
|
3
|
+
export interface PermissionLedgerAdapterOptions {
|
|
4
|
+
/** The WPM instance to attach callbacks to. */
|
|
5
|
+
wallet: WalletPermissionsManager;
|
|
6
|
+
/** Persistent store for permission grants. */
|
|
7
|
+
store: IPermissionStore;
|
|
8
|
+
/** UI prompt callbacks. */
|
|
9
|
+
prompt: PermissionPromptHandler;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Bridges an {@link IPermissionStore} to a {@link WalletPermissionsManager}.
|
|
13
|
+
*
|
|
14
|
+
* The adapter owns WPM's permission callbacks. On every permission check:
|
|
15
|
+
*
|
|
16
|
+
* 1. It looks up a stored grant in the supplied store.
|
|
17
|
+
* 2. If a valid unexpired grant exists, it calls
|
|
18
|
+
* `wallet.grantPermission({ ephemeral: true })` silently. WPM resolves
|
|
19
|
+
* the pending dApp call without writing anything to the chain.
|
|
20
|
+
* 3. Otherwise it delegates to the host app's prompt handler. On approval,
|
|
21
|
+
* it writes the grant to the store and calls `grantPermission` ephemerally.
|
|
22
|
+
*
|
|
23
|
+
* BRC-73 grouped permissions are handled via `dismissGroupedPermission` after
|
|
24
|
+
* writing each sub-permission to the store. WPM's downstream per-method checks
|
|
25
|
+
* then find the entries on their individual callback paths. When a site adds
|
|
26
|
+
* a new permission between visits, the prompt receives only the missing
|
|
27
|
+
* subset — already-granted permissions are not re-listed.
|
|
28
|
+
*
|
|
29
|
+
* DSAP (spending) cap enforcement reads actual confirmed spend from the
|
|
30
|
+
* wallet's action history via `WalletPermissionsManager.querySpentSince` —
|
|
31
|
+
* the same mechanism WPM uses natively. No ledger-side counter is
|
|
32
|
+
* maintained, so failed broadcasts cannot cause drift.
|
|
33
|
+
*
|
|
34
|
+
* Level-2 counterparty pacts (`onCounterpartyPermissionRequested`) remain
|
|
35
|
+
* on-chain: the adapter just routes the UI decision to WPM's native
|
|
36
|
+
* `grantCounterpartyPermission` / `denyCounterpartyPermission`. If the
|
|
37
|
+
* consumer omits `prompt.onCounterpartyPermissionRequested`, the adapter
|
|
38
|
+
* auto-denies counterparty requests so the dApp call fails cleanly instead
|
|
39
|
+
* of hanging forever.
|
|
40
|
+
*
|
|
41
|
+
* Call {@link dispose} to unbind callbacks when tearing down the wallet.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PermissionLedgerAdapter {
|
|
44
|
+
private readonly wallet;
|
|
45
|
+
private readonly store;
|
|
46
|
+
private readonly prompt;
|
|
47
|
+
private boundCallbacks;
|
|
48
|
+
constructor(options: PermissionLedgerAdapterOptions);
|
|
49
|
+
private bindCallbacks;
|
|
50
|
+
/** Unbinds every callback this adapter registered on the wallet. */
|
|
51
|
+
dispose(): void;
|
|
52
|
+
private handleSingle;
|
|
53
|
+
private handleSpending;
|
|
54
|
+
private handleGrouped;
|
|
55
|
+
private handleCounterparty;
|
|
56
|
+
private safeDeny;
|
|
57
|
+
/**
|
|
58
|
+
* Return the full union of local (ledger) grants and on-chain WPM tokens.
|
|
59
|
+
*
|
|
60
|
+
* Under the default setup, the on-chain side contains only level-2
|
|
61
|
+
* counterparty pacts (and any pre-migration tokens that still exist).
|
|
62
|
+
* Records are tagged with `source: 'ledger' | 'onchain'` so the revoke
|
|
63
|
+
* handler can route correctly.
|
|
64
|
+
*/
|
|
65
|
+
listAllPermissions(): Promise<PermissionRecord[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Revoke a single ledger-backed grant.
|
|
68
|
+
*
|
|
69
|
+
* To revoke an on-chain (counterparty) token, call
|
|
70
|
+
* `wallet.revokePermission(token)` directly with the raw WPM token.
|
|
71
|
+
*/
|
|
72
|
+
revokeLedgerGrant(key: PermissionKey): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Revoke every grant for an originator across both stores.
|
|
75
|
+
*
|
|
76
|
+
* Returns counts of what was removed from each side.
|
|
77
|
+
*/
|
|
78
|
+
revokeAllForOriginator(originator: string): Promise<{
|
|
79
|
+
ledger: number;
|
|
80
|
+
onchain: number;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Return the satoshi amount spent against the given DSAP grant in the
|
|
84
|
+
* current UTC month, read from the wallet's action history.
|
|
85
|
+
*
|
|
86
|
+
* Delegates to `WalletPermissionsManager.querySpentSince` for accuracy and
|
|
87
|
+
* cross-device consistency — the ledger does not track spend itself.
|
|
88
|
+
*/
|
|
89
|
+
querySpent(key: PermissionKey): Promise<number>;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/permissions/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAQX,wBAAwB,EAExB,MAAM,qBAAqB,CAAA;AAS5B,OAAO,KAAK,EACX,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAEhB,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,8BAA8B;IAC9C,+CAA+C;IAC/C,MAAM,EAAE,wBAAwB,CAAA;IAChC,8CAA8C;IAC9C,KAAK,EAAE,gBAAgB,CAAA;IACvB,2BAA2B;IAC3B,MAAM,EAAE,uBAAuB,CAAA;CAC/B;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,cAAc,CAAoC;gBAE9C,OAAO,EAAE,8BAA8B;IAOnD,OAAO,CAAC,aAAa;IAoBrB,oEAAoE;IACpE,OAAO,IAAI,IAAI;YAWD,YAAY;YAmCZ,cAAc;YAwDd,aAAa;YAgEb,kBAAkB;YA8BlB,QAAQ;IAQtB;;;;;;;OAOG;IACG,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAqCvD;;;;;OAKG;IACG,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D;;;;OAIG;IACG,sBAAsB,CAC3B,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAO/C;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;CAMrD"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { filterGroupedByMissing, isExpired, normalizeOriginator, permissionKeyFromRequest, permissionKeyToString, permissionKeysFromGroup, } from './key';
|
|
2
|
+
/**
|
|
3
|
+
* Bridges an {@link IPermissionStore} to a {@link WalletPermissionsManager}.
|
|
4
|
+
*
|
|
5
|
+
* The adapter owns WPM's permission callbacks. On every permission check:
|
|
6
|
+
*
|
|
7
|
+
* 1. It looks up a stored grant in the supplied store.
|
|
8
|
+
* 2. If a valid unexpired grant exists, it calls
|
|
9
|
+
* `wallet.grantPermission({ ephemeral: true })` silently. WPM resolves
|
|
10
|
+
* the pending dApp call without writing anything to the chain.
|
|
11
|
+
* 3. Otherwise it delegates to the host app's prompt handler. On approval,
|
|
12
|
+
* it writes the grant to the store and calls `grantPermission` ephemerally.
|
|
13
|
+
*
|
|
14
|
+
* BRC-73 grouped permissions are handled via `dismissGroupedPermission` after
|
|
15
|
+
* writing each sub-permission to the store. WPM's downstream per-method checks
|
|
16
|
+
* then find the entries on their individual callback paths. When a site adds
|
|
17
|
+
* a new permission between visits, the prompt receives only the missing
|
|
18
|
+
* subset — already-granted permissions are not re-listed.
|
|
19
|
+
*
|
|
20
|
+
* DSAP (spending) cap enforcement reads actual confirmed spend from the
|
|
21
|
+
* wallet's action history via `WalletPermissionsManager.querySpentSince` —
|
|
22
|
+
* the same mechanism WPM uses natively. No ledger-side counter is
|
|
23
|
+
* maintained, so failed broadcasts cannot cause drift.
|
|
24
|
+
*
|
|
25
|
+
* Level-2 counterparty pacts (`onCounterpartyPermissionRequested`) remain
|
|
26
|
+
* on-chain: the adapter just routes the UI decision to WPM's native
|
|
27
|
+
* `grantCounterpartyPermission` / `denyCounterpartyPermission`. If the
|
|
28
|
+
* consumer omits `prompt.onCounterpartyPermissionRequested`, the adapter
|
|
29
|
+
* auto-denies counterparty requests so the dApp call fails cleanly instead
|
|
30
|
+
* of hanging forever.
|
|
31
|
+
*
|
|
32
|
+
* Call {@link dispose} to unbind callbacks when tearing down the wallet.
|
|
33
|
+
*/
|
|
34
|
+
export class PermissionLedgerAdapter {
|
|
35
|
+
wallet;
|
|
36
|
+
store;
|
|
37
|
+
prompt;
|
|
38
|
+
boundCallbacks = [];
|
|
39
|
+
constructor(options) {
|
|
40
|
+
this.wallet = options.wallet;
|
|
41
|
+
this.store = options.store;
|
|
42
|
+
this.prompt = options.prompt;
|
|
43
|
+
this.bindCallbacks();
|
|
44
|
+
}
|
|
45
|
+
bindCallbacks() {
|
|
46
|
+
const bind = (name, handler) => {
|
|
47
|
+
const id = this.wallet.bindCallback(name, handler);
|
|
48
|
+
this.boundCallbacks.push([name, id]);
|
|
49
|
+
};
|
|
50
|
+
const single = (r) => this.handleSingle(r);
|
|
51
|
+
const spending = (r) => this.handleSpending(r);
|
|
52
|
+
const grouped = (r) => this.handleGrouped(r);
|
|
53
|
+
const counterparty = (r) => this.handleCounterparty(r);
|
|
54
|
+
bind('onProtocolPermissionRequested', single);
|
|
55
|
+
bind('onBasketAccessRequested', single);
|
|
56
|
+
bind('onCertificateAccessRequested', single);
|
|
57
|
+
bind('onSpendingAuthorizationRequested', spending);
|
|
58
|
+
bind('onGroupedPermissionRequested', grouped);
|
|
59
|
+
bind('onCounterpartyPermissionRequested', counterparty);
|
|
60
|
+
}
|
|
61
|
+
/** Unbinds every callback this adapter registered on the wallet. */
|
|
62
|
+
dispose() {
|
|
63
|
+
for (const [name, id] of this.boundCallbacks) {
|
|
64
|
+
this.wallet.unbindCallback(name, id);
|
|
65
|
+
}
|
|
66
|
+
this.boundCallbacks = [];
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------
|
|
69
|
+
// Handlers
|
|
70
|
+
// ---------------------------------------------------------------------
|
|
71
|
+
async handleSingle(request) {
|
|
72
|
+
try {
|
|
73
|
+
const key = permissionKeyFromRequest(request);
|
|
74
|
+
const existing = await this.store.findGrant(key);
|
|
75
|
+
if (existing && !isExpired(existing.expiry)) {
|
|
76
|
+
await this.wallet.grantPermission({
|
|
77
|
+
requestID: request.requestID,
|
|
78
|
+
ephemeral: true,
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const decision = await this.prompt.onPermissionRequested(request);
|
|
83
|
+
if (decision.approved) {
|
|
84
|
+
await this.store.putGrant({
|
|
85
|
+
key,
|
|
86
|
+
expiry: decision.expiry ?? 0,
|
|
87
|
+
grantedAt: Date.now(),
|
|
88
|
+
reason: request.reason,
|
|
89
|
+
});
|
|
90
|
+
await this.wallet.grantPermission({
|
|
91
|
+
requestID: request.requestID,
|
|
92
|
+
ephemeral: true,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
await this.wallet.denyPermission(request.requestID);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
await this.safeDeny(request.requestID);
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async handleSpending(request) {
|
|
105
|
+
try {
|
|
106
|
+
if (request.type !== 'spending' || !request.spending) {
|
|
107
|
+
await this.wallet.denyPermission(request.requestID);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const key = permissionKeyFromRequest(request);
|
|
111
|
+
const needed = request.spending.satoshis;
|
|
112
|
+
const existing = await this.store.findGrant(key);
|
|
113
|
+
if (existing &&
|
|
114
|
+
!isExpired(existing.expiry) &&
|
|
115
|
+
existing.key.type === 'spending' &&
|
|
116
|
+
existing.authorizedAmount != null) {
|
|
117
|
+
// Read actual confirmed spend for this originator this month directly
|
|
118
|
+
// from the wallet's action history. WPM's own `querySpentSince` only
|
|
119
|
+
// reads `token.originator` + `token.rawOriginator`, so we can pass a
|
|
120
|
+
// minimal stub rather than reconstruct a full PermissionToken.
|
|
121
|
+
const spent = await this.wallet.querySpentSince({
|
|
122
|
+
originator: existing.key.originator,
|
|
123
|
+
});
|
|
124
|
+
if (spent + needed <= existing.authorizedAmount) {
|
|
125
|
+
await this.wallet.grantPermission({
|
|
126
|
+
requestID: request.requestID,
|
|
127
|
+
ephemeral: true,
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const decision = await this.prompt.onPermissionRequested(request);
|
|
133
|
+
if (decision.approved) {
|
|
134
|
+
await this.store.putGrant({
|
|
135
|
+
key,
|
|
136
|
+
expiry: decision.expiry ?? 0,
|
|
137
|
+
grantedAt: Date.now(),
|
|
138
|
+
reason: request.reason,
|
|
139
|
+
authorizedAmount: decision.authorizedAmount ?? needed,
|
|
140
|
+
});
|
|
141
|
+
await this.wallet.grantPermission({
|
|
142
|
+
requestID: request.requestID,
|
|
143
|
+
ephemeral: true,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
await this.wallet.denyPermission(request.requestID);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
await this.safeDeny(request.requestID);
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async handleGrouped(request) {
|
|
156
|
+
try {
|
|
157
|
+
const neededKeys = permissionKeysFromGroup(request.originator, request.permissions);
|
|
158
|
+
const lookups = await Promise.all(neededKeys.map((k) => this.store.findGrant(k)));
|
|
159
|
+
const missingKeys = new Set();
|
|
160
|
+
for (let i = 0; i < neededKeys.length; i++) {
|
|
161
|
+
const g = lookups[i];
|
|
162
|
+
if (!g || isExpired(g.expiry)) {
|
|
163
|
+
missingKeys.add(permissionKeyToString(neededKeys[i]));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (missingKeys.size === 0) {
|
|
167
|
+
await this.wallet.dismissGroupedPermission(request.requestID);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Hand the prompt only the sub-permissions that still need approval.
|
|
171
|
+
// On first visit this equals the full bundle; on a revisit where the
|
|
172
|
+
// site has added one new permission, only that new one is shown.
|
|
173
|
+
const trimmedPermissions = filterGroupedByMissing(request.originator, request.permissions, missingKeys);
|
|
174
|
+
const decision = await this.prompt.onGroupedPermissionRequested({
|
|
175
|
+
...request,
|
|
176
|
+
permissions: trimmedPermissions,
|
|
177
|
+
});
|
|
178
|
+
if (!decision.approved) {
|
|
179
|
+
await this.wallet.denyGroupedPermission(request.requestID);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const normalized = normalizeOriginator(request.originator);
|
|
183
|
+
const grantedKeys = permissionKeysFromGroup(normalized, decision.granted);
|
|
184
|
+
const now = Date.now();
|
|
185
|
+
const expiry = decision.expiry ?? 0;
|
|
186
|
+
for (const key of grantedKeys) {
|
|
187
|
+
const grant = { key, expiry, grantedAt: now };
|
|
188
|
+
if (key.type === 'spending' && decision.granted.spendingAuthorization) {
|
|
189
|
+
grant.authorizedAmount = decision.granted.spendingAuthorization.amount;
|
|
190
|
+
grant.reason = decision.granted.spendingAuthorization.description;
|
|
191
|
+
}
|
|
192
|
+
await this.store.putGrant(grant);
|
|
193
|
+
}
|
|
194
|
+
await this.wallet.dismissGroupedPermission(request.requestID);
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
await this.wallet
|
|
198
|
+
.denyGroupedPermission(request.requestID)
|
|
199
|
+
.catch(() => undefined);
|
|
200
|
+
throw err;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async handleCounterparty(request) {
|
|
204
|
+
// Level-2 counterparty pacts stay on-chain. The adapter does not consult
|
|
205
|
+
// the local store for these; it just routes the consumer's UI decision
|
|
206
|
+
// to WPM's native grant/deny (which writes the token to the chain).
|
|
207
|
+
const handler = this.prompt.onCounterpartyPermissionRequested;
|
|
208
|
+
if (!handler) {
|
|
209
|
+
await this.wallet.denyCounterpartyPermission(request.requestID);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const decision = await handler(request);
|
|
214
|
+
if (decision.approved) {
|
|
215
|
+
await this.wallet.grantCounterpartyPermission({
|
|
216
|
+
requestID: request.requestID,
|
|
217
|
+
granted: decision.granted,
|
|
218
|
+
expiry: decision.expiry,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
await this.wallet.denyCounterpartyPermission(request.requestID);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
await this.wallet
|
|
227
|
+
.denyCounterpartyPermission(request.requestID)
|
|
228
|
+
.catch(() => undefined);
|
|
229
|
+
throw err;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async safeDeny(requestID) {
|
|
233
|
+
await this.wallet.denyPermission(requestID).catch(() => undefined);
|
|
234
|
+
}
|
|
235
|
+
// ---------------------------------------------------------------------
|
|
236
|
+
// Management helpers (for consumers to rebuild UIs)
|
|
237
|
+
// ---------------------------------------------------------------------
|
|
238
|
+
/**
|
|
239
|
+
* Return the full union of local (ledger) grants and on-chain WPM tokens.
|
|
240
|
+
*
|
|
241
|
+
* Under the default setup, the on-chain side contains only level-2
|
|
242
|
+
* counterparty pacts (and any pre-migration tokens that still exist).
|
|
243
|
+
* Records are tagged with `source: 'ledger' | 'onchain'` so the revoke
|
|
244
|
+
* handler can route correctly.
|
|
245
|
+
*/
|
|
246
|
+
async listAllPermissions() {
|
|
247
|
+
const [ledger, protocols, baskets, spending, certs] = await Promise.all([
|
|
248
|
+
this.store.listGrants(),
|
|
249
|
+
this.wallet.listProtocolPermissions({}),
|
|
250
|
+
this.wallet.listBasketAccess({}),
|
|
251
|
+
this.wallet.listSpendingAuthorizations({}),
|
|
252
|
+
this.wallet.listCertificateAccess({}),
|
|
253
|
+
]);
|
|
254
|
+
const ledgerRecords = ledger.map((g) => ({
|
|
255
|
+
source: 'ledger',
|
|
256
|
+
...g,
|
|
257
|
+
}));
|
|
258
|
+
const onChain = [
|
|
259
|
+
...protocols.map((t) => ({
|
|
260
|
+
source: 'onchain',
|
|
261
|
+
type: 'protocol',
|
|
262
|
+
token: t,
|
|
263
|
+
})),
|
|
264
|
+
...baskets.map((t) => ({
|
|
265
|
+
source: 'onchain',
|
|
266
|
+
type: 'basket',
|
|
267
|
+
token: t,
|
|
268
|
+
})),
|
|
269
|
+
...spending.map((t) => ({
|
|
270
|
+
source: 'onchain',
|
|
271
|
+
type: 'spending',
|
|
272
|
+
token: t,
|
|
273
|
+
})),
|
|
274
|
+
...certs.map((t) => ({
|
|
275
|
+
source: 'onchain',
|
|
276
|
+
type: 'certificate',
|
|
277
|
+
token: t,
|
|
278
|
+
})),
|
|
279
|
+
];
|
|
280
|
+
return [...ledgerRecords, ...onChain];
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Revoke a single ledger-backed grant.
|
|
284
|
+
*
|
|
285
|
+
* To revoke an on-chain (counterparty) token, call
|
|
286
|
+
* `wallet.revokePermission(token)` directly with the raw WPM token.
|
|
287
|
+
*/
|
|
288
|
+
async revokeLedgerGrant(key) {
|
|
289
|
+
await this.store.deleteGrant(key);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Revoke every grant for an originator across both stores.
|
|
293
|
+
*
|
|
294
|
+
* Returns counts of what was removed from each side.
|
|
295
|
+
*/
|
|
296
|
+
async revokeAllForOriginator(originator) {
|
|
297
|
+
const normalized = normalizeOriginator(originator);
|
|
298
|
+
const ledgerCount = await this.store.deleteAllForOriginator(normalized);
|
|
299
|
+
const onchainRevoked = await this.wallet.revokeAllForOriginator(normalized);
|
|
300
|
+
return { ledger: ledgerCount, onchain: onchainRevoked.length };
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Return the satoshi amount spent against the given DSAP grant in the
|
|
304
|
+
* current UTC month, read from the wallet's action history.
|
|
305
|
+
*
|
|
306
|
+
* Delegates to `WalletPermissionsManager.querySpentSince` for accuracy and
|
|
307
|
+
* cross-device consistency — the ledger does not track spend itself.
|
|
308
|
+
*/
|
|
309
|
+
async querySpent(key) {
|
|
310
|
+
if (key.type !== 'spending')
|
|
311
|
+
return 0;
|
|
312
|
+
return this.wallet.querySpentSince({
|
|
313
|
+
originator: key.originator,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/permissions/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IPermissionStore, ListGrantsFilter, PermissionKey, StoredGrant } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Reference `IPermissionStore` that keeps grants in a JS `Map`.
|
|
4
|
+
*
|
|
5
|
+
* Useful for tests, Node/server environments, and as a template for custom
|
|
6
|
+
* backends. Browser apps should prefer `IndexedDbPermissionStore` from
|
|
7
|
+
* `@1sat/wallet-browser` — it's the default for `createWebWallet`.
|
|
8
|
+
*/
|
|
9
|
+
export declare class InMemoryPermissionStore implements IPermissionStore {
|
|
10
|
+
private grants;
|
|
11
|
+
findGrant(key: PermissionKey): Promise<StoredGrant | null>;
|
|
12
|
+
putGrant(grant: StoredGrant): Promise<void>;
|
|
13
|
+
deleteGrant(key: PermissionKey): Promise<void>;
|
|
14
|
+
deleteAllForOriginator(originator: string): Promise<number>;
|
|
15
|
+
listGrants(filter?: ListGrantsFilter): Promise<StoredGrant[]>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=in-memory-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-store.d.ts","sourceRoot":"","sources":["../../src/permissions/in-memory-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,MAAM,SAAS,CAAA;AAEhB;;;;;;GAMG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,MAAM,CAAiC;IAEzC,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAI1D,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW3D,UAAU,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAUnE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { permissionKeyToString } from './key';
|
|
2
|
+
/**
|
|
3
|
+
* Reference `IPermissionStore` that keeps grants in a JS `Map`.
|
|
4
|
+
*
|
|
5
|
+
* Useful for tests, Node/server environments, and as a template for custom
|
|
6
|
+
* backends. Browser apps should prefer `IndexedDbPermissionStore` from
|
|
7
|
+
* `@1sat/wallet-browser` — it's the default for `createWebWallet`.
|
|
8
|
+
*/
|
|
9
|
+
export class InMemoryPermissionStore {
|
|
10
|
+
grants = new Map();
|
|
11
|
+
async findGrant(key) {
|
|
12
|
+
return this.grants.get(permissionKeyToString(key)) ?? null;
|
|
13
|
+
}
|
|
14
|
+
async putGrant(grant) {
|
|
15
|
+
this.grants.set(permissionKeyToString(grant.key), grant);
|
|
16
|
+
}
|
|
17
|
+
async deleteGrant(key) {
|
|
18
|
+
this.grants.delete(permissionKeyToString(key));
|
|
19
|
+
}
|
|
20
|
+
async deleteAllForOriginator(originator) {
|
|
21
|
+
let removed = 0;
|
|
22
|
+
for (const [id, grant] of this.grants) {
|
|
23
|
+
if (grant.key.originator === originator) {
|
|
24
|
+
this.grants.delete(id);
|
|
25
|
+
removed++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return removed;
|
|
29
|
+
}
|
|
30
|
+
async listGrants(filter) {
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const grant of this.grants.values()) {
|
|
33
|
+
if (filter?.originator && grant.key.originator !== filter.originator)
|
|
34
|
+
continue;
|
|
35
|
+
if (filter?.type && grant.key.type !== filter.type)
|
|
36
|
+
continue;
|
|
37
|
+
out.push(grant);
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=in-memory-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-store.js","sourceRoot":"","sources":["../../src/permissions/in-memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAQ7C;;;;;;GAMG;AACH,MAAM,OAAO,uBAAuB;IAC3B,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAA;IAE/C,KAAK,CAAC,SAAS,CAAC,GAAkB;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAkB;QAChC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAA;IACzD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAkB;QACnC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,UAAkB;QAC9C,IAAI,OAAO,GAAG,CAAC,CAAA;QACf,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACzC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACtB,OAAO,EAAE,CAAA;YACV,CAAC;QACF,CAAC;QACD,OAAO,OAAO,CAAA;IACf,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAyB;QACzC,MAAM,GAAG,GAAkB,EAAE,CAAA;QAC7B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,IAAI,MAAM,EAAE,UAAU,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU;gBACnE,SAAQ;YACT,IAAI,MAAM,EAAE,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI;gBAAE,SAAQ;YAC5D,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChB,CAAC;QACD,OAAO,GAAG,CAAA;IACX,CAAC;CACD"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { PermissionLedgerAdapter } from './adapter';
|
|
2
|
+
export type { PermissionLedgerAdapterOptions } from './adapter';
|
|
3
|
+
export { InMemoryPermissionStore } from './in-memory-store';
|
|
4
|
+
export { filterGroupedByMissing, isExpired, normalizeOriginator, permissionKeyFromRequest, permissionKeysFromGroup, permissionKeyToString, } from './key';
|
|
5
|
+
export type { CounterpartyPermissionPromptDecision, GroupedPermissionPromptDecision, IPermissionStore, ListGrantsFilter, PermissionKey, PermissionPromptDecision, PermissionPromptHandler, PermissionRecord, PermissionRecordSource, PermissionType, StoredGrant, } from './types';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACnD,YAAY,EAAE,8BAA8B,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,sBAAsB,EACtB,SAAS,EACT,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,OAAO,CAAA;AACd,YAAY,EACX,oCAAoC,EACpC,+BAA+B,EAC/B,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,GACX,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { PermissionLedgerAdapter } from './adapter';
|
|
2
|
+
export { InMemoryPermissionStore } from './in-memory-store';
|
|
3
|
+
export { filterGroupedByMissing, isExpired, normalizeOriginator, permissionKeyFromRequest, permissionKeysFromGroup, permissionKeyToString, } from './key';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,sBAAsB,EACtB,SAAS,EACT,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,OAAO,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GroupedPermissions, PermissionRequest } from '@bsv/wallet-toolbox';
|
|
2
|
+
import type { PermissionKey } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Normalize an originator to the same canonical form WPM uses internally.
|
|
5
|
+
*
|
|
6
|
+
* - Lowercase hostname
|
|
7
|
+
* - Strip default ports (80 for http, 443 for https)
|
|
8
|
+
* - Preserve non-default ports
|
|
9
|
+
* - Fall back to lowercase trim on URL-parse failure
|
|
10
|
+
*
|
|
11
|
+
* Kept in sync with `WalletPermissionsManager#normalizeOriginator`. See
|
|
12
|
+
* `WPM-COUPLINGS.md` in this package for the fragility contract.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeOriginator(originator: string | undefined | null): string;
|
|
15
|
+
/**
|
|
16
|
+
* Build a normalized `PermissionKey` from a WPM `PermissionRequest`.
|
|
17
|
+
*
|
|
18
|
+
* Throws if the request is missing required fields for its type (this should
|
|
19
|
+
* not happen in practice — WPM always populates these before firing callbacks).
|
|
20
|
+
*/
|
|
21
|
+
export declare function permissionKeyFromRequest(request: PermissionRequest): PermissionKey;
|
|
22
|
+
/**
|
|
23
|
+
* Produce a canonical string representation of a `PermissionKey`.
|
|
24
|
+
*
|
|
25
|
+
* Suitable for use as a `Map` key or a storage index. Keys round-trip
|
|
26
|
+
* through `permissionKeyToString` safely — two requests that share the same
|
|
27
|
+
* normalized originator + parameters produce the same string.
|
|
28
|
+
*
|
|
29
|
+
* Certificate fields are sorted before joining so that field order does
|
|
30
|
+
* not affect key identity.
|
|
31
|
+
*/
|
|
32
|
+
export declare function permissionKeyToString(key: PermissionKey): string;
|
|
33
|
+
/**
|
|
34
|
+
* Build the list of `PermissionKey`s implied by a BRC-73 grouped-permission bundle.
|
|
35
|
+
*
|
|
36
|
+
* Used by the adapter to check whether every sub-permission in a grouped
|
|
37
|
+
* request is already present in the store before deciding whether to prompt.
|
|
38
|
+
*
|
|
39
|
+
* Counterparty-less (`counterparty: ''`) protocol entries are skipped —
|
|
40
|
+
* they belong to a separate counterparty-pact flow and should not be
|
|
41
|
+
* matched as regular grants.
|
|
42
|
+
*/
|
|
43
|
+
export declare function permissionKeysFromGroup(originator: string, permissions: GroupedPermissions): PermissionKey[];
|
|
44
|
+
/** True if `expiry` (UNIX seconds, 0 = never) has passed. */
|
|
45
|
+
export declare function isExpired(expiry: number, now?: number): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Build a new `GroupedPermissions` bundle containing only the sub-permissions
|
|
48
|
+
* whose canonical key string is present in `missingKeys`.
|
|
49
|
+
*
|
|
50
|
+
* Used by the adapter to trim an already-partially-granted bundle before
|
|
51
|
+
* handing it to the consumer's prompt handler — the user should only see
|
|
52
|
+
* permissions that still need approval, not ones they've already granted.
|
|
53
|
+
*/
|
|
54
|
+
export declare function filterGroupedByMissing(originator: string, permissions: GroupedPermissions, missingKeys: Set<string>): GroupedPermissions;
|
|
55
|
+
//# sourceMappingURL=key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/permissions/key.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAQ5C;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GACnC,MAAM,CAmBR;AAWD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,iBAAiB,GACxB,aAAa,CA2Cf;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAWhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,kBAAkB,GAC7B,aAAa,EAAE,CAsCjB;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAG3E;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,kBAAkB,EAC/B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,kBAAkB,CA8DpB"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/** Default ports stripped from normalized originators (mirrors WPM). */
|
|
2
|
+
const DEFAULT_PORTS = {
|
|
3
|
+
'http:': '80',
|
|
4
|
+
'https:': '443',
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Normalize an originator to the same canonical form WPM uses internally.
|
|
8
|
+
*
|
|
9
|
+
* - Lowercase hostname
|
|
10
|
+
* - Strip default ports (80 for http, 443 for https)
|
|
11
|
+
* - Preserve non-default ports
|
|
12
|
+
* - Fall back to lowercase trim on URL-parse failure
|
|
13
|
+
*
|
|
14
|
+
* Kept in sync with `WalletPermissionsManager#normalizeOriginator`. See
|
|
15
|
+
* `WPM-COUPLINGS.md` in this package for the fragility contract.
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeOriginator(originator) {
|
|
18
|
+
if (!originator)
|
|
19
|
+
return '';
|
|
20
|
+
const trimmed = originator.trim();
|
|
21
|
+
if (!trimmed)
|
|
22
|
+
return '';
|
|
23
|
+
try {
|
|
24
|
+
const hasScheme = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(trimmed);
|
|
25
|
+
const candidate = hasScheme ? trimmed : `https://${trimmed}`;
|
|
26
|
+
const url = new URL(candidate);
|
|
27
|
+
if (!url.hostname)
|
|
28
|
+
return trimmed.toLowerCase();
|
|
29
|
+
const hostname = url.hostname.toLowerCase();
|
|
30
|
+
const needsBrackets = hostname.includes(':');
|
|
31
|
+
const baseHost = needsBrackets ? `[${hostname}]` : hostname;
|
|
32
|
+
const port = url.port;
|
|
33
|
+
const defaultPort = DEFAULT_PORTS[url.protocol];
|
|
34
|
+
if (port && defaultPort && port === defaultPort)
|
|
35
|
+
return baseHost;
|
|
36
|
+
return port ? `${baseHost}:${port}` : baseHost;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return trimmed.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Default the counterparty per WPM's convention (level-1 protocols always use `''`). */
|
|
43
|
+
function defaultCounterparty(protocolID, counterparty) {
|
|
44
|
+
if (protocolID[0] === 1)
|
|
45
|
+
return '';
|
|
46
|
+
return counterparty ?? 'self';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Build a normalized `PermissionKey` from a WPM `PermissionRequest`.
|
|
50
|
+
*
|
|
51
|
+
* Throws if the request is missing required fields for its type (this should
|
|
52
|
+
* not happen in practice — WPM always populates these before firing callbacks).
|
|
53
|
+
*/
|
|
54
|
+
export function permissionKeyFromRequest(request) {
|
|
55
|
+
const originator = normalizeOriginator(request.originator);
|
|
56
|
+
switch (request.type) {
|
|
57
|
+
case 'protocol': {
|
|
58
|
+
if (!request.protocolID) {
|
|
59
|
+
throw new Error('Protocol permission request missing protocolID');
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
type: 'protocol',
|
|
63
|
+
originator,
|
|
64
|
+
privileged: !!request.privileged,
|
|
65
|
+
protocolLevel: request.protocolID[0],
|
|
66
|
+
protocolName: request.protocolID[1],
|
|
67
|
+
counterparty: defaultCounterparty(request.protocolID, request.counterparty),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
case 'basket': {
|
|
71
|
+
if (!request.basket) {
|
|
72
|
+
throw new Error('Basket permission request missing basket');
|
|
73
|
+
}
|
|
74
|
+
return { type: 'basket', originator, basket: request.basket };
|
|
75
|
+
}
|
|
76
|
+
case 'certificate': {
|
|
77
|
+
if (!request.certificate) {
|
|
78
|
+
throw new Error('Certificate permission request missing certificate details');
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
type: 'certificate',
|
|
82
|
+
originator,
|
|
83
|
+
privileged: !!request.privileged,
|
|
84
|
+
verifier: request.certificate.verifier,
|
|
85
|
+
certType: request.certificate.certType,
|
|
86
|
+
fields: [...request.certificate.fields].sort(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
case 'spending':
|
|
90
|
+
return { type: 'spending', originator };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Produce a canonical string representation of a `PermissionKey`.
|
|
95
|
+
*
|
|
96
|
+
* Suitable for use as a `Map` key or a storage index. Keys round-trip
|
|
97
|
+
* through `permissionKeyToString` safely — two requests that share the same
|
|
98
|
+
* normalized originator + parameters produce the same string.
|
|
99
|
+
*
|
|
100
|
+
* Certificate fields are sorted before joining so that field order does
|
|
101
|
+
* not affect key identity.
|
|
102
|
+
*/
|
|
103
|
+
export function permissionKeyToString(key) {
|
|
104
|
+
switch (key.type) {
|
|
105
|
+
case 'protocol':
|
|
106
|
+
return `proto:${key.originator}:${key.privileged}:${key.protocolLevel},${key.protocolName}:${key.counterparty}`;
|
|
107
|
+
case 'basket':
|
|
108
|
+
return `basket:${key.originator}:${key.basket}`;
|
|
109
|
+
case 'certificate':
|
|
110
|
+
return `cert:${key.originator}:${key.privileged}:${key.verifier}:${key.certType}:${[...key.fields].sort().join('|')}`;
|
|
111
|
+
case 'spending':
|
|
112
|
+
return `spend:${key.originator}`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Build the list of `PermissionKey`s implied by a BRC-73 grouped-permission bundle.
|
|
117
|
+
*
|
|
118
|
+
* Used by the adapter to check whether every sub-permission in a grouped
|
|
119
|
+
* request is already present in the store before deciding whether to prompt.
|
|
120
|
+
*
|
|
121
|
+
* Counterparty-less (`counterparty: ''`) protocol entries are skipped —
|
|
122
|
+
* they belong to a separate counterparty-pact flow and should not be
|
|
123
|
+
* matched as regular grants.
|
|
124
|
+
*/
|
|
125
|
+
export function permissionKeysFromGroup(originator, permissions) {
|
|
126
|
+
const normalized = normalizeOriginator(originator);
|
|
127
|
+
const keys = [];
|
|
128
|
+
if (permissions.spendingAuthorization) {
|
|
129
|
+
keys.push({ type: 'spending', originator: normalized });
|
|
130
|
+
}
|
|
131
|
+
for (const p of permissions.protocolPermissions ?? []) {
|
|
132
|
+
if (p.counterparty === '')
|
|
133
|
+
continue;
|
|
134
|
+
const level = p.protocolID[0];
|
|
135
|
+
const counterparty = level === 1 ? '' : (p.counterparty ?? 'self');
|
|
136
|
+
keys.push({
|
|
137
|
+
type: 'protocol',
|
|
138
|
+
originator: normalized,
|
|
139
|
+
privileged: false,
|
|
140
|
+
protocolLevel: level,
|
|
141
|
+
protocolName: p.protocolID[1],
|
|
142
|
+
counterparty,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
for (const b of permissions.basketAccess ?? []) {
|
|
146
|
+
keys.push({ type: 'basket', originator: normalized, basket: b.basket });
|
|
147
|
+
}
|
|
148
|
+
for (const c of permissions.certificateAccess ?? []) {
|
|
149
|
+
keys.push({
|
|
150
|
+
type: 'certificate',
|
|
151
|
+
originator: normalized,
|
|
152
|
+
privileged: false,
|
|
153
|
+
verifier: c.verifierPublicKey,
|
|
154
|
+
certType: c.type,
|
|
155
|
+
fields: [...c.fields].sort(),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return keys;
|
|
159
|
+
}
|
|
160
|
+
/** True if `expiry` (UNIX seconds, 0 = never) has passed. */
|
|
161
|
+
export function isExpired(expiry, now = Date.now()) {
|
|
162
|
+
if (!expiry)
|
|
163
|
+
return false;
|
|
164
|
+
return expiry * 1000 < now;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Build a new `GroupedPermissions` bundle containing only the sub-permissions
|
|
168
|
+
* whose canonical key string is present in `missingKeys`.
|
|
169
|
+
*
|
|
170
|
+
* Used by the adapter to trim an already-partially-granted bundle before
|
|
171
|
+
* handing it to the consumer's prompt handler — the user should only see
|
|
172
|
+
* permissions that still need approval, not ones they've already granted.
|
|
173
|
+
*/
|
|
174
|
+
export function filterGroupedByMissing(originator, permissions, missingKeys) {
|
|
175
|
+
const normalized = normalizeOriginator(originator);
|
|
176
|
+
const out = { description: permissions.description };
|
|
177
|
+
if (permissions.spendingAuthorization) {
|
|
178
|
+
const key = permissionKeyToString({
|
|
179
|
+
type: 'spending',
|
|
180
|
+
originator: normalized,
|
|
181
|
+
});
|
|
182
|
+
if (missingKeys.has(key)) {
|
|
183
|
+
out.spendingAuthorization = permissions.spendingAuthorization;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const protocolPermissions = [];
|
|
187
|
+
for (const p of permissions.protocolPermissions ?? []) {
|
|
188
|
+
if (p.counterparty === '')
|
|
189
|
+
continue;
|
|
190
|
+
const level = p.protocolID[0];
|
|
191
|
+
const counterparty = level === 1 ? '' : (p.counterparty ?? 'self');
|
|
192
|
+
const key = permissionKeyToString({
|
|
193
|
+
type: 'protocol',
|
|
194
|
+
originator: normalized,
|
|
195
|
+
privileged: false,
|
|
196
|
+
protocolLevel: level,
|
|
197
|
+
protocolName: p.protocolID[1],
|
|
198
|
+
counterparty,
|
|
199
|
+
});
|
|
200
|
+
if (missingKeys.has(key))
|
|
201
|
+
protocolPermissions.push(p);
|
|
202
|
+
}
|
|
203
|
+
if (protocolPermissions.length > 0)
|
|
204
|
+
out.protocolPermissions = protocolPermissions;
|
|
205
|
+
const basketAccess = [];
|
|
206
|
+
for (const b of permissions.basketAccess ?? []) {
|
|
207
|
+
const key = permissionKeyToString({
|
|
208
|
+
type: 'basket',
|
|
209
|
+
originator: normalized,
|
|
210
|
+
basket: b.basket,
|
|
211
|
+
});
|
|
212
|
+
if (missingKeys.has(key))
|
|
213
|
+
basketAccess.push(b);
|
|
214
|
+
}
|
|
215
|
+
if (basketAccess.length > 0)
|
|
216
|
+
out.basketAccess = basketAccess;
|
|
217
|
+
const certificateAccess = [];
|
|
218
|
+
for (const c of permissions.certificateAccess ?? []) {
|
|
219
|
+
const key = permissionKeyToString({
|
|
220
|
+
type: 'certificate',
|
|
221
|
+
originator: normalized,
|
|
222
|
+
privileged: false,
|
|
223
|
+
verifier: c.verifierPublicKey,
|
|
224
|
+
certType: c.type,
|
|
225
|
+
fields: [...c.fields].sort(),
|
|
226
|
+
});
|
|
227
|
+
if (missingKeys.has(key))
|
|
228
|
+
certificateAccess.push(c);
|
|
229
|
+
}
|
|
230
|
+
if (certificateAccess.length > 0)
|
|
231
|
+
out.certificateAccess = certificateAccess;
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../src/permissions/key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { CounterpartyPermissionRequest, CounterpartyPermissions, GroupedPermissionRequest, GroupedPermissions, PermissionRequest, PermissionToken } from '@bsv/wallet-toolbox';
|
|
2
|
+
/** The four BRC-100 permission categories. */
|
|
3
|
+
export type PermissionType = 'protocol' | 'basket' | 'certificate' | 'spending';
|
|
4
|
+
/** A normalized permission key, uniquely identifying a (originator, category, parameters) tuple. */
|
|
5
|
+
export type PermissionKey = {
|
|
6
|
+
type: 'protocol';
|
|
7
|
+
originator: string;
|
|
8
|
+
privileged: boolean;
|
|
9
|
+
protocolLevel: 0 | 1 | 2;
|
|
10
|
+
protocolName: string;
|
|
11
|
+
counterparty: string;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'basket';
|
|
14
|
+
originator: string;
|
|
15
|
+
basket: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: 'certificate';
|
|
18
|
+
originator: string;
|
|
19
|
+
privileged: boolean;
|
|
20
|
+
verifier: string;
|
|
21
|
+
certType: string;
|
|
22
|
+
fields: string[];
|
|
23
|
+
} | {
|
|
24
|
+
type: 'spending';
|
|
25
|
+
originator: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A persisted permission grant.
|
|
29
|
+
*
|
|
30
|
+
* For spending (DSAP) grants, the ledger only stores the user-authorized cap
|
|
31
|
+
* (`authorizedAmount`). Actual monthly spend is read from the wallet's
|
|
32
|
+
* action history on every cap check via `WalletPermissionsManager.querySpentSince`
|
|
33
|
+
* — the same mechanism WPM uses natively, so spent accounting remains exact
|
|
34
|
+
* and cross-device consistent.
|
|
35
|
+
*/
|
|
36
|
+
export interface StoredGrant {
|
|
37
|
+
key: PermissionKey;
|
|
38
|
+
/** UNIX seconds, 0 for never expires. */
|
|
39
|
+
expiry: number;
|
|
40
|
+
/** UNIX milliseconds when this grant was created. */
|
|
41
|
+
grantedAt: number;
|
|
42
|
+
/** Optional human-readable reason captured from the request. */
|
|
43
|
+
reason?: string;
|
|
44
|
+
/** DSAP only — monthly spending cap (in satoshis). */
|
|
45
|
+
authorizedAmount?: number;
|
|
46
|
+
}
|
|
47
|
+
/** Filter passed to `IPermissionStore.listGrants`. */
|
|
48
|
+
export interface ListGrantsFilter {
|
|
49
|
+
originator?: string;
|
|
50
|
+
type?: PermissionType;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Storage backend for permission grants.
|
|
54
|
+
*
|
|
55
|
+
* Implementations should be keyed by the canonical string form of the
|
|
56
|
+
* `PermissionKey` (use `permissionKeyToString` from `./key`).
|
|
57
|
+
*
|
|
58
|
+
* All methods are async to allow implementations backed by persistent
|
|
59
|
+
* stores (IndexedDB, chrome.storage, file, etc.).
|
|
60
|
+
*/
|
|
61
|
+
export interface IPermissionStore {
|
|
62
|
+
findGrant(key: PermissionKey): Promise<StoredGrant | null>;
|
|
63
|
+
putGrant(grant: StoredGrant): Promise<void>;
|
|
64
|
+
deleteGrant(key: PermissionKey): Promise<void>;
|
|
65
|
+
deleteAllForOriginator(originator: string): Promise<number>;
|
|
66
|
+
listGrants(filter?: ListGrantsFilter): Promise<StoredGrant[]>;
|
|
67
|
+
}
|
|
68
|
+
/** User decision returned from a single-permission prompt. */
|
|
69
|
+
export type PermissionPromptDecision = {
|
|
70
|
+
approved: true;
|
|
71
|
+
/** Optional override for the grant expiry in UNIX seconds. */
|
|
72
|
+
expiry?: number;
|
|
73
|
+
/** DSAP only — override the authorized amount (e.g. user chose a larger cap). */
|
|
74
|
+
authorizedAmount?: number;
|
|
75
|
+
} | {
|
|
76
|
+
approved: false;
|
|
77
|
+
};
|
|
78
|
+
/** User decision returned from a BRC-73 grouped-permission prompt. */
|
|
79
|
+
export type GroupedPermissionPromptDecision = {
|
|
80
|
+
approved: true;
|
|
81
|
+
/** Subset of the requested permissions that the user agreed to. */
|
|
82
|
+
granted: Partial<GroupedPermissions>;
|
|
83
|
+
expiry?: number;
|
|
84
|
+
} | {
|
|
85
|
+
approved: false;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* User decision returned from a level-2 counterparty pact prompt.
|
|
89
|
+
*
|
|
90
|
+
* `granted` is a `Partial<CounterpartyPermissions>` because users typically
|
|
91
|
+
* approve a subset of the requested protocols, matching WPM's
|
|
92
|
+
* `grantCounterpartyPermission` signature.
|
|
93
|
+
*/
|
|
94
|
+
export type CounterpartyPermissionPromptDecision = {
|
|
95
|
+
approved: true;
|
|
96
|
+
granted: Partial<CounterpartyPermissions>;
|
|
97
|
+
expiry?: number;
|
|
98
|
+
} | {
|
|
99
|
+
approved: false;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Prompt callbacks supplied by the consumer (the host app).
|
|
103
|
+
*
|
|
104
|
+
* The adapter calls these when a grant is needed after the store lookup
|
|
105
|
+
* comes back empty. Counterparty prompts are optional — if omitted, the
|
|
106
|
+
* adapter auto-denies counterparty requests so the dApp call fails cleanly
|
|
107
|
+
* instead of hanging forever.
|
|
108
|
+
*/
|
|
109
|
+
export interface PermissionPromptHandler {
|
|
110
|
+
onPermissionRequested(request: PermissionRequest & {
|
|
111
|
+
requestID: string;
|
|
112
|
+
}): Promise<PermissionPromptDecision>;
|
|
113
|
+
onGroupedPermissionRequested(request: GroupedPermissionRequest): Promise<GroupedPermissionPromptDecision>;
|
|
114
|
+
onCounterpartyPermissionRequested?(request: CounterpartyPermissionRequest): Promise<CounterpartyPermissionPromptDecision>;
|
|
115
|
+
}
|
|
116
|
+
/** The source a permission record was loaded from when listing all permissions. */
|
|
117
|
+
export type PermissionRecordSource = 'ledger' | 'onchain';
|
|
118
|
+
/**
|
|
119
|
+
* Unified record returned by the adapter's `listAllPermissions` helper.
|
|
120
|
+
*
|
|
121
|
+
* `source: 'ledger'` records are local `StoredGrant`s; `source: 'onchain'`
|
|
122
|
+
* records are WPM `PermissionToken` shapes surfaced for level-2 counterparty
|
|
123
|
+
* pacts (and any pre-migration on-chain tokens that still exist).
|
|
124
|
+
*/
|
|
125
|
+
export type PermissionRecord = ({
|
|
126
|
+
source: 'ledger';
|
|
127
|
+
} & StoredGrant) | {
|
|
128
|
+
source: 'onchain';
|
|
129
|
+
type: PermissionType;
|
|
130
|
+
token: PermissionToken;
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/permissions/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/permissions/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/wallet",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.42",
|
|
4
4
|
"description": "BRC-100 wallet engine for 1Sat Ordinals SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,19 +28,19 @@
|
|
|
28
28
|
],
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@1sat/client": "0.0.
|
|
32
|
-
"@1sat/types": "0.0.
|
|
33
|
-
"@1sat/templates": "0.0.
|
|
31
|
+
"@1sat/client": "0.0.21",
|
|
32
|
+
"@1sat/types": "0.0.17",
|
|
33
|
+
"@1sat/templates": "0.0.8",
|
|
34
34
|
"@bopen-io/templates": "^1.2.3",
|
|
35
35
|
"@msgpack/msgpack": "^3.1.3",
|
|
36
36
|
"fflate": "^0.8.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@bsv/sdk": "^2.0.
|
|
40
|
-
"@bsv/wallet-toolbox": "^2.1.
|
|
39
|
+
"@bsv/sdk": "^2.0.13",
|
|
40
|
+
"@bsv/wallet-toolbox": "^2.1.21"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@bsv/sdk": "^2.0.
|
|
43
|
+
"@bsv/sdk": "^2.0.13",
|
|
44
44
|
"@types/chrome": "^0.1.32",
|
|
45
45
|
"typescript": "^5.9.3"
|
|
46
46
|
}
|