@bsv/wallet-toolbox-mobile 2.4.1 → 2.4.3
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/out/src/Wallet.d.ts +1 -1
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js +8 -7
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletPermissionsManager.d.ts +33 -0
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js +132 -37
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/monitor/tasks/TaskArcSSE.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskArcSSE.js +11 -7
- package/out/src/monitor/tasks/TaskArcSSE.js.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskCheckForProofs.js +10 -10
- package/out/src/monitor/tasks/TaskCheckForProofs.js.map +1 -1
- package/out/src/monitor/tasks/TaskReviewStatus.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskReviewStatus.js +7 -2
- package/out/src/monitor/tasks/TaskReviewStatus.js.map +1 -1
- package/out/src/monitor/tasks/TaskUnFail.d.ts.map +1 -1
- package/out/src/monitor/tasks/TaskUnFail.js +2 -57
- package/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts +1 -0
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +10 -4
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/sdk/types.d.ts +1 -1
- package/out/src/sdk/types.d.ts.map +1 -1
- package/out/src/services/Services.d.ts.map +1 -1
- package/out/src/services/Services.js +39 -19
- package/out/src/services/Services.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js +4 -0
- package/out/src/services/chaintracker/chaintracks/GoChaintracksServiceClient.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js +2 -0
- package/out/src/services/chaintracker/chaintracks/Ingest/WhatsOnChainIngestorWs.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +2 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js +1 -0
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js.map +1 -1
- package/out/src/services/createDefaultWalletServicesOptions.d.ts.map +1 -1
- package/out/src/services/createDefaultWalletServicesOptions.js +17 -3
- package/out/src/services/createDefaultWalletServicesOptions.js.map +1 -1
- package/out/src/services/networkConfig.d.ts +29 -0
- package/out/src/services/networkConfig.d.ts.map +1 -0
- package/out/src/services/networkConfig.js +54 -0
- package/out/src/services/networkConfig.js.map +1 -0
- package/out/src/services/providers/Arcade.d.ts.map +1 -1
- package/out/src/services/providers/Arcade.js +6 -2
- package/out/src/services/providers/Arcade.js.map +1 -1
- package/out/src/services/providers/SdkWhatsOnChain.d.ts +1 -1
- package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -1
- package/out/src/services/providers/SdkWhatsOnChain.js +12 -4
- package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -1
- package/out/src/signer/methods/buildSignableTransaction.d.ts.map +1 -1
- package/out/src/signer/methods/buildSignableTransaction.js +3 -1
- package/out/src/signer/methods/buildSignableTransaction.js.map +1 -1
- package/out/src/signer/methods/completeSignedTransaction.d.ts.map +1 -1
- package/out/src/signer/methods/completeSignedTransaction.js +5 -3
- package/out/src/signer/methods/completeSignedTransaction.js.map +1 -1
- package/out/src/signer/methods/createAction.d.ts.map +1 -1
- package/out/src/signer/methods/createAction.js +12 -5
- package/out/src/signer/methods/createAction.js.map +1 -1
- package/out/src/signer/methods/resultBeef.d.ts +4 -0
- package/out/src/signer/methods/resultBeef.d.ts.map +1 -0
- package/out/src/signer/methods/resultBeef.js +12 -0
- package/out/src/signer/methods/resultBeef.js.map +1 -0
- package/out/src/signer/methods/signAction.d.ts.map +1 -1
- package/out/src/signer/methods/signAction.js +6 -1
- package/out/src/signer/methods/signAction.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +17 -0
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +206 -13
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/methods/createAction.js +17 -4
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/getBeefForTransaction.d.ts.map +1 -1
- package/out/src/storage/methods/getBeefForTransaction.js +47 -24
- package/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/out/src/storage/methods/internalizeAction.js +3 -3
- package/out/src/storage/methods/internalizeAction.js.map +1 -1
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +5 -4
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/remoting/BinaryJson.d.ts +10 -0
- package/out/src/storage/remoting/BinaryJson.d.ts.map +1 -0
- package/out/src/storage/remoting/BinaryJson.js +172 -0
- package/out/src/storage/remoting/BinaryJson.js.map +1 -0
- package/out/src/storage/remoting/StorageClient.d.ts +2 -2
- package/out/src/storage/remoting/StorageClient.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClient.js +14 -5
- package/out/src/storage/remoting/StorageClient.js.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.d.ts +11 -1
- package/out/src/storage/remoting/StorageClientBase.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.js +4 -1
- package/out/src/storage/remoting/StorageClientBase.js.map +1 -1
- package/out/src/storage/remoting/StorageMobile.d.ts +2 -2
- package/out/src/storage/remoting/StorageMobile.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageMobile.js +14 -5
- package/out/src/storage/remoting/StorageMobile.js.map +1 -1
- package/out/src/storage/schema/tables/TableAuthSession.d.ts +20 -0
- package/out/src/storage/schema/tables/TableAuthSession.d.ts.map +1 -0
- package/out/src/storage/schema/tables/TableAuthSession.js +15 -0
- package/out/src/storage/schema/tables/TableAuthSession.js.map +1 -0
- package/out/src/storage/schema/tables/index.d.ts +1 -0
- package/out/src/storage/schema/tables/index.d.ts.map +1 -1
- package/out/src/storage/schema/tables/index.js +1 -0
- package/out/src/storage/schema/tables/index.js.map +1 -1
- package/out/src/storage/storageProviderHelpers.d.ts +5 -4
- package/out/src/storage/storageProviderHelpers.d.ts.map +1 -1
- package/out/src/storage/storageProviderHelpers.js +7 -6
- package/out/src/storage/storageProviderHelpers.js.map +1 -1
- package/out/src/utility/utilityHelpers.d.ts.map +1 -1
- package/out/src/utility/utilityHelpers.js +2 -0
- package/out/src/utility/utilityHelpers.js.map +1 -1
- package/package.json +2 -2
|
@@ -91,11 +91,28 @@ class WalletPermissionsManager {
|
|
|
91
91
|
/** Cache recently confirmed permissions to avoid repeated lookups. */
|
|
92
92
|
permissionCache = new Map();
|
|
93
93
|
recentGrants = new Map();
|
|
94
|
+
/**
|
|
95
|
+
* Token mints currently being written on-chain, keyed by permission cache
|
|
96
|
+
* key. A granted permission is only cached once its token finishes minting
|
|
97
|
+
* (network seconds); ensures arriving in that window await the in-flight
|
|
98
|
+
* mint instead of re-prompting the user for a permission they just granted.
|
|
99
|
+
* Stored promises never reject.
|
|
100
|
+
*/
|
|
101
|
+
mintsInFlight = new Map();
|
|
94
102
|
manifestCache = new Map();
|
|
95
103
|
manifestFetchInProgress = new Map();
|
|
96
104
|
static MANIFEST_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
97
105
|
groupedPermissionFlowTail = new Map();
|
|
98
106
|
pactEstablishedCache = new Map();
|
|
107
|
+
/**
|
|
108
|
+
* Parsed BEEF bundles keyed by the raw BEEF array of a `listOutputs`
|
|
109
|
+
* result, so token scans parse each bundle once instead of once per output.
|
|
110
|
+
* `null` records a bundle that failed to parse. WeakMap-keyed so entries
|
|
111
|
+
* are released with their results.
|
|
112
|
+
*/
|
|
113
|
+
parsedBeefCache = new WeakMap();
|
|
114
|
+
/** Counts token-field decrypts so long scans can periodically yield. */
|
|
115
|
+
tokenFieldDecryptCount = 0;
|
|
99
116
|
/** How long a cached permission remains valid (5 minutes). */
|
|
100
117
|
static CACHE_TTL_MS = 5 * 60 * 1000;
|
|
101
118
|
/** Window during which freshly granted permissions are auto-allowed (except spending). */
|
|
@@ -382,26 +399,45 @@ class WalletPermissionsManager {
|
|
|
382
399
|
}
|
|
383
400
|
this.activeRequests.delete(params.requestID);
|
|
384
401
|
// 3) If `ephemeral !== true`, we create or renew an on-chain token
|
|
385
|
-
if (!params.ephemeral) {
|
|
386
|
-
const request = matching.request;
|
|
387
|
-
if (request.renewal) {
|
|
388
|
-
// renewal => spend the old token, produce a new one
|
|
389
|
-
await this.renewPermissionOnChain(request.previousToken, request, params.expiry || 0, // default: never expires
|
|
390
|
-
params.amount);
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
// brand-new permission token
|
|
394
|
-
await this.createPermissionOnChain(request, params.expiry || 0, // default: never expires
|
|
395
|
-
params.amount);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
402
|
// Only cache non-ephemeral permissions
|
|
399
403
|
// Ephemeral permissions should not be cached as they are one-time authorizations
|
|
400
404
|
if (!params.ephemeral) {
|
|
405
|
+
const request = matching.request;
|
|
401
406
|
const expiry = params.expiry || 0; // default: never expires
|
|
402
|
-
const key = this.buildRequestKey(
|
|
407
|
+
const key = this.buildRequestKey(request);
|
|
408
|
+
// Several first-contact prompts for the same permission can stack up
|
|
409
|
+
// before any token exists (e.g. one per usage type). Granting them all
|
|
410
|
+
// should yield ONE token: if an identical non-renewal grant just minted
|
|
411
|
+
// (or is minting), don't mint a duplicate. Spending authorizations are
|
|
412
|
+
// excluded — their tokens carry amounts, so every grant is honored.
|
|
413
|
+
let skipDuplicateMint = !request.renewal &&
|
|
414
|
+
request.type !== 'spending' &&
|
|
415
|
+
(this.isPermissionCached(key) || this.isRecentlyGranted(key) || this.mintsInFlight.has(key));
|
|
416
|
+
if (skipDuplicateMint) {
|
|
417
|
+
const inFlight = this.mintsInFlight.get(key);
|
|
418
|
+
if (inFlight != null) {
|
|
419
|
+
await inFlight;
|
|
420
|
+
// The awaited mint may have failed; only skip if it landed.
|
|
421
|
+
skipDuplicateMint = this.isPermissionCached(key) || this.isRecentlyGranted(key);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (!skipDuplicateMint) {
|
|
425
|
+
const mint = request.renewal
|
|
426
|
+
? this.renewPermissionOnChain(request.previousToken, request, expiry, params.amount)
|
|
427
|
+
: this.createPermissionOnChain(request, expiry, params.amount);
|
|
428
|
+
// Publish the in-flight mint so concurrent ensures for the same
|
|
429
|
+
// permission wait for it instead of re-prompting (stored promise
|
|
430
|
+
// never rejects; failures still propagate to this caller below).
|
|
431
|
+
this.mintsInFlight.set(key, mint.then(() => { }, () => { }));
|
|
432
|
+
try {
|
|
433
|
+
await mint;
|
|
434
|
+
}
|
|
435
|
+
finally {
|
|
436
|
+
this.mintsInFlight.delete(key);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
403
439
|
this.cachePermission(key, expiry);
|
|
404
|
-
this.markRecentGrant(
|
|
440
|
+
this.markRecentGrant(request);
|
|
405
441
|
}
|
|
406
442
|
}
|
|
407
443
|
/**
|
|
@@ -417,8 +453,12 @@ class WalletPermissionsManager {
|
|
|
417
453
|
throw new Error('Request ID not found.');
|
|
418
454
|
}
|
|
419
455
|
// 2) Reject all matching requests, deleting the entry
|
|
456
|
+
// Denials carry the canonical machine-readable code so applications can
|
|
457
|
+
// distinguish user denial from other failures (matches denyActiveRequest).
|
|
458
|
+
const err = new Error('Permission denied.');
|
|
459
|
+
err.code = 'ERR_PERMISSION_DENIED';
|
|
420
460
|
for (const x of matching.pending) {
|
|
421
|
-
x.reject(
|
|
461
|
+
x.reject(err);
|
|
422
462
|
}
|
|
423
463
|
this.activeRequests.delete(requestID);
|
|
424
464
|
}
|
|
@@ -664,7 +704,7 @@ class WalletPermissionsManager {
|
|
|
664
704
|
if (!privileged && this.isWhitelistedCounterpartyProtocol(counterparty, protocolID))
|
|
665
705
|
return true;
|
|
666
706
|
const cacheKey = this.buildRequestKey({ type: 'protocol', originator, privileged, protocolID, counterparty });
|
|
667
|
-
if (
|
|
707
|
+
if (await this.hasRecentOrPendingGrant(cacheKey))
|
|
668
708
|
return true;
|
|
669
709
|
// 4) Attempt to find a valid token in the internal basket
|
|
670
710
|
const token = await this.findProtocolToken(originator, privileged, protocolID, counterparty, /* includeExpired= */ true, lookupValues);
|
|
@@ -704,7 +744,7 @@ class WalletPermissionsManager {
|
|
|
704
744
|
if (!this.isBasketUsageRequired(usageType))
|
|
705
745
|
return true;
|
|
706
746
|
const cacheKey = this.buildRequestKey({ type: 'basket', originator, basket });
|
|
707
|
-
if (
|
|
747
|
+
if (await this.hasRecentOrPendingGrant(cacheKey))
|
|
708
748
|
return true;
|
|
709
749
|
const token = await this.findBasketToken(originator, basket, true, lookupValues);
|
|
710
750
|
if (token == null) {
|
|
@@ -753,10 +793,7 @@ class WalletPermissionsManager {
|
|
|
753
793
|
privileged,
|
|
754
794
|
certificate: { verifier, certType, fields }
|
|
755
795
|
});
|
|
756
|
-
if (this.
|
|
757
|
-
return true;
|
|
758
|
-
}
|
|
759
|
-
if (this.isRecentlyGranted(cacheKey)) {
|
|
796
|
+
if (await this.hasRecentOrPendingGrant(cacheKey)) {
|
|
760
797
|
return true;
|
|
761
798
|
}
|
|
762
799
|
const token = await this.findCertificateToken(originator, privileged, verifier, certType, fields,
|
|
@@ -807,7 +844,10 @@ class WalletPermissionsManager {
|
|
|
807
844
|
return true;
|
|
808
845
|
}
|
|
809
846
|
const cacheKey = this.buildRequestKey({ type: 'spending', originator, spending: { satoshis } });
|
|
810
|
-
|
|
847
|
+
// Spending keys are amount-scoped. The recent-grant window this adds sits
|
|
848
|
+
// inside the pre-existing permissionCache window grantPermission already
|
|
849
|
+
// wrote for spending, so accounting exposure is unchanged.
|
|
850
|
+
if (await this.hasRecentOrPendingGrant(cacheKey)) {
|
|
811
851
|
return true;
|
|
812
852
|
}
|
|
813
853
|
const token = await this.findSpendingToken(originator, lookupValues);
|
|
@@ -1016,11 +1056,13 @@ class WalletPermissionsManager {
|
|
|
1016
1056
|
(async () => {
|
|
1017
1057
|
if (groupPermissions.spendingAuthorization == null)
|
|
1018
1058
|
return undefined;
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1059
|
+
// A standing authorization is a grant regardless of how much of the
|
|
1060
|
+
// monthly allowance has been used — exhaustion is handled by renewal
|
|
1061
|
+
// at spend time. Checking remaining headroom here re-requests (and,
|
|
1062
|
+
// if approved, re-mints) spending after any monthly usage.
|
|
1063
|
+
const { normalized, lookupValues } = this.prepareOriginator(originator);
|
|
1064
|
+
const token = await this.findSpendingToken(normalized, lookupValues);
|
|
1065
|
+
return token != null ? undefined : groupPermissions.spendingAuthorization;
|
|
1024
1066
|
})(),
|
|
1025
1067
|
(async () => {
|
|
1026
1068
|
const protocolChecks = await Promise.all((groupPermissions.protocolPermissions || []).map(async (p) => {
|
|
@@ -1571,7 +1613,45 @@ class WalletPermissionsManager {
|
|
|
1571
1613
|
}, this.adminOriginator);
|
|
1572
1614
|
return ciphertext;
|
|
1573
1615
|
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Extracts a transaction from a `listOutputs` result's BEEF bundle, parsing
|
|
1618
|
+
* the bundle only once per result. Calling
|
|
1619
|
+
* `Transaction.fromBEEF(result.BEEF, txid)` per output re-parses the entire
|
|
1620
|
+
* bundle every time — O(n²) in the number of outputs — which can block the
|
|
1621
|
+
* caller's thread (in browser wallets, the UI) for seconds on large
|
|
1622
|
+
* permission baskets.
|
|
1623
|
+
*/
|
|
1624
|
+
transactionFromResultBeef(result, txid) {
|
|
1625
|
+
const beef = result.BEEF;
|
|
1626
|
+
if (beef != null) {
|
|
1627
|
+
let parsed = this.parsedBeefCache.get(beef);
|
|
1628
|
+
if (parsed === undefined) {
|
|
1629
|
+
try {
|
|
1630
|
+
parsed = sdk_1.Beef.fromBinary(beef);
|
|
1631
|
+
}
|
|
1632
|
+
catch {
|
|
1633
|
+
parsed = null;
|
|
1634
|
+
}
|
|
1635
|
+
this.parsedBeefCache.set(beef, parsed);
|
|
1636
|
+
}
|
|
1637
|
+
// findAtomicTransaction (not findTxid().tx) matches fromBEEF exactly:
|
|
1638
|
+
// it attaches merkle paths and sourceTransaction ancestry, which token
|
|
1639
|
+
// consumers rely on when re-serializing via tx.toBEEF().
|
|
1640
|
+
const tx = parsed?.findAtomicTransaction(txid);
|
|
1641
|
+
if (tx != null)
|
|
1642
|
+
return tx;
|
|
1643
|
+
}
|
|
1644
|
+
// Preserve the original behavior (including throwing) for bundles the
|
|
1645
|
+
// fast path can't serve.
|
|
1646
|
+
return sdk_1.Transaction.fromBEEF(beef ?? [], txid);
|
|
1647
|
+
}
|
|
1574
1648
|
async decryptPermissionTokenField(ciphertext) {
|
|
1649
|
+
// Field decrypts run in tight loops over every token in a basket; yield a
|
|
1650
|
+
// macrotask periodically so large scans don't starve the caller's event
|
|
1651
|
+
// loop (in browser wallets, that means blocking rendering and input).
|
|
1652
|
+
if (++this.tokenFieldDecryptCount % 8 === 0) {
|
|
1653
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1654
|
+
}
|
|
1575
1655
|
try {
|
|
1576
1656
|
const { plaintext } = await this.underlying.decrypt({
|
|
1577
1657
|
ciphertext,
|
|
@@ -1715,7 +1795,7 @@ class WalletPermissionsManager {
|
|
|
1715
1795
|
}, this.adminOriginator);
|
|
1716
1796
|
for (const out of result.outputs) {
|
|
1717
1797
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
1718
|
-
const tx =
|
|
1798
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1719
1799
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1720
1800
|
if (dec?.fields == null || dec.fields.length < 6)
|
|
1721
1801
|
continue;
|
|
@@ -1774,7 +1854,7 @@ class WalletPermissionsManager {
|
|
|
1774
1854
|
if (seen.has(out.outpoint))
|
|
1775
1855
|
continue;
|
|
1776
1856
|
const [txid, vout] = this.parseOutpoint(out.outpoint);
|
|
1777
|
-
const tx =
|
|
1857
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1778
1858
|
const dec = sdk_1.PushDrop.decode(tx.outputs[vout].lockingScript);
|
|
1779
1859
|
if (dec?.fields == null || dec.fields.length < 6)
|
|
1780
1860
|
continue;
|
|
@@ -1818,7 +1898,7 @@ class WalletPermissionsManager {
|
|
|
1818
1898
|
}, this.adminOriginator);
|
|
1819
1899
|
for (const out of result.outputs) {
|
|
1820
1900
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
1821
|
-
const tx =
|
|
1901
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1822
1902
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1823
1903
|
if (!dec?.fields || dec.fields.length < 3)
|
|
1824
1904
|
continue;
|
|
@@ -1858,7 +1938,7 @@ class WalletPermissionsManager {
|
|
|
1858
1938
|
}, this.adminOriginator);
|
|
1859
1939
|
for (const out of result.outputs) {
|
|
1860
1940
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
1861
|
-
const tx =
|
|
1941
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1862
1942
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
1863
1943
|
if (!dec?.fields || dec.fields.length < 6)
|
|
1864
1944
|
continue;
|
|
@@ -1909,7 +1989,7 @@ class WalletPermissionsManager {
|
|
|
1909
1989
|
}, this.adminOriginator);
|
|
1910
1990
|
for (const out of result.outputs) {
|
|
1911
1991
|
const [txid, outputIndexStr] = out.outpoint.split('.');
|
|
1912
|
-
const tx =
|
|
1992
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
1913
1993
|
const dec = sdk_1.PushDrop.decode(tx.outputs[Number(outputIndexStr)].lockingScript);
|
|
1914
1994
|
if (!dec?.fields || dec.fields.length < 2)
|
|
1915
1995
|
continue;
|
|
@@ -2366,7 +2446,7 @@ class WalletPermissionsManager {
|
|
|
2366
2446
|
if (seen.has(out.outpoint))
|
|
2367
2447
|
continue;
|
|
2368
2448
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
2369
|
-
const tx =
|
|
2449
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
2370
2450
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2371
2451
|
if (!dec?.fields || dec.fields.length < 6)
|
|
2372
2452
|
continue;
|
|
@@ -2434,7 +2514,7 @@ class WalletPermissionsManager {
|
|
|
2434
2514
|
if (seen.has(out.outpoint))
|
|
2435
2515
|
continue;
|
|
2436
2516
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
2437
|
-
const tx =
|
|
2517
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
2438
2518
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2439
2519
|
if (!dec?.fields || dec.fields.length < 3)
|
|
2440
2520
|
continue;
|
|
@@ -2497,7 +2577,7 @@ class WalletPermissionsManager {
|
|
|
2497
2577
|
const tokens = [];
|
|
2498
2578
|
for (const out of result.outputs) {
|
|
2499
2579
|
const [txid, outputIndexStr] = out.outpoint.split('.');
|
|
2500
|
-
const tx =
|
|
2580
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
2501
2581
|
const dec = sdk_1.PushDrop.decode(tx.outputs[Number(outputIndexStr)].lockingScript);
|
|
2502
2582
|
if (!dec?.fields || dec.fields.length < 2)
|
|
2503
2583
|
continue;
|
|
@@ -2568,7 +2648,7 @@ class WalletPermissionsManager {
|
|
|
2568
2648
|
if (seen.has(out.outpoint))
|
|
2569
2649
|
continue;
|
|
2570
2650
|
const [txid, outputIndex] = this.parseOutpoint(out.outpoint);
|
|
2571
|
-
const tx =
|
|
2651
|
+
const tx = this.transactionFromResultBeef(result, txid);
|
|
2572
2652
|
const dec = sdk_1.PushDrop.decode(tx.outputs[outputIndex].lockingScript);
|
|
2573
2653
|
if (!dec?.fields || dec.fields.length < 6)
|
|
2574
2654
|
continue;
|
|
@@ -3506,6 +3586,21 @@ class WalletPermissionsManager {
|
|
|
3506
3586
|
return true;
|
|
3507
3587
|
return false;
|
|
3508
3588
|
}
|
|
3589
|
+
/**
|
|
3590
|
+
* Whether the permission is satisfied without consulting on-chain tokens:
|
|
3591
|
+
* cached, recently granted, or — when the user just granted it and its
|
|
3592
|
+
* token is still minting — after the in-flight mint settles. Spares the
|
|
3593
|
+
* user a duplicate prompt for a grant they already made moments ago.
|
|
3594
|
+
*/
|
|
3595
|
+
async hasRecentOrPendingGrant(cacheKey) {
|
|
3596
|
+
if (this.isPermissionCached(cacheKey) || this.isRecentlyGranted(cacheKey))
|
|
3597
|
+
return true;
|
|
3598
|
+
const inFlight = this.mintsInFlight.get(cacheKey);
|
|
3599
|
+
if (inFlight == null)
|
|
3600
|
+
return false;
|
|
3601
|
+
await inFlight;
|
|
3602
|
+
return this.isPermissionCached(cacheKey) || this.isRecentlyGranted(cacheKey);
|
|
3603
|
+
}
|
|
3509
3604
|
/**
|
|
3510
3605
|
* Returns true if we have a cached record that the permission identified by
|
|
3511
3606
|
* `key` is valid and unexpired.
|