@opendatalabs/vana-sdk 0.1.0-alpha.2e77fcc → 0.1.0-alpha.3041a59
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/controllers/__tests__/data-consistency-integration.test.d.ts +7 -0
- package/dist/controllers/__tests__/operations.processQueue.test.d.ts +1 -0
- package/dist/controllers/data.cjs +255 -143
- package/dist/controllers/data.cjs.map +1 -1
- package/dist/controllers/data.d.ts +25 -10
- package/dist/controllers/data.js +268 -146
- package/dist/controllers/data.js.map +1 -1
- package/dist/controllers/operations.cjs +430 -0
- package/dist/controllers/operations.cjs.map +1 -0
- package/dist/controllers/operations.d.ts +229 -0
- package/dist/controllers/operations.js +406 -0
- package/dist/controllers/operations.js.map +1 -0
- package/dist/controllers/permissions.cjs +516 -183
- package/dist/controllers/permissions.cjs.map +1 -1
- package/dist/controllers/permissions.d.ts +126 -28
- package/dist/controllers/permissions.js +516 -183
- package/dist/controllers/permissions.js.map +1 -1
- package/dist/controllers/schemas.cjs +81 -4
- package/dist/controllers/schemas.cjs.map +1 -1
- package/dist/controllers/schemas.d.ts +41 -0
- package/dist/controllers/schemas.js +81 -4
- package/dist/controllers/schemas.js.map +1 -1
- package/dist/controllers/server.cjs +251 -42
- package/dist/controllers/server.cjs.map +1 -1
- package/dist/controllers/server.d.ts +111 -14
- package/dist/controllers/server.js +251 -42
- package/dist/controllers/server.js.map +1 -1
- package/dist/core/__tests__/health.test.d.ts +1 -0
- package/dist/core/__tests__/inMemoryNonceManager.test.d.ts +1 -0
- package/dist/core/__tests__/nonceManager.test.d.ts +1 -0
- package/dist/core/__tests__/pollingManager.test.d.ts +4 -0
- package/dist/core/health.cjs +289 -0
- package/dist/core/health.cjs.map +1 -0
- package/dist/core/health.d.ts +143 -0
- package/dist/core/health.js +265 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/inMemoryNonceManager.cjs +138 -0
- package/dist/core/inMemoryNonceManager.cjs.map +1 -0
- package/dist/core/inMemoryNonceManager.d.ts +69 -0
- package/dist/core/inMemoryNonceManager.js +114 -0
- package/dist/core/inMemoryNonceManager.js.map +1 -0
- package/dist/core/nonceManager.cjs +304 -0
- package/dist/core/nonceManager.cjs.map +1 -0
- package/dist/core/nonceManager.d.ts +116 -0
- package/dist/core/nonceManager.js +280 -0
- package/dist/core/nonceManager.js.map +1 -0
- package/dist/core/pollingManager.cjs +292 -0
- package/dist/core/pollingManager.cjs.map +1 -0
- package/dist/core/pollingManager.d.ts +120 -0
- package/dist/core/pollingManager.js +268 -0
- package/dist/core/pollingManager.js.map +1 -0
- package/dist/core.cjs +5 -0
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +11 -5
- package/dist/core.js +5 -0
- package/dist/core.js.map +1 -1
- package/dist/crypto/ecies/base.cjs +16 -3
- package/dist/crypto/ecies/base.cjs.map +1 -1
- package/dist/crypto/ecies/base.js +16 -3
- package/dist/crypto/ecies/base.js.map +1 -1
- package/dist/errors.cjs +29 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -1
- package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs +162 -0
- package/dist/generated/abi/DataPortabilityGranteesImplementation.cjs.map +1 -1
- package/dist/generated/abi/DataPortabilityGranteesImplementation.d.ts +123 -0
- package/dist/generated/abi/DataPortabilityGranteesImplementation.js +162 -0
- package/dist/generated/abi/DataPortabilityGranteesImplementation.js.map +1 -1
- package/dist/generated/abi/index.d.ts +123 -0
- package/dist/generated/server/server-exports.cjs +22 -0
- package/dist/generated/server/server-exports.cjs.map +1 -1
- package/dist/generated/server/server-exports.d.ts +27 -10
- package/dist/generated/server/server-exports.js +17 -0
- package/dist/generated/server/server-exports.js.map +1 -1
- package/dist/generated/server/server.cjs.map +1 -1
- package/dist/generated/server/server.d.ts +771 -402
- package/dist/generated/subgraph.cjs +797 -32
- package/dist/generated/subgraph.cjs.map +1 -1
- package/dist/generated/subgraph.d.ts +135 -0
- package/dist/generated/subgraph.js +792 -32
- package/dist/generated/subgraph.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +2 -0
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +17 -0
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.d.ts +25 -5
- package/dist/index.node.js +15 -1
- package/dist/index.node.js.map +1 -1
- package/dist/lib/__tests__/redisAtomicStore.test.d.ts +1 -0
- package/dist/lib/redisAtomicStore.cjs +201 -0
- package/dist/lib/redisAtomicStore.cjs.map +1 -0
- package/dist/lib/redisAtomicStore.d.ts +120 -0
- package/dist/lib/redisAtomicStore.js +177 -0
- package/dist/lib/redisAtomicStore.js.map +1 -0
- package/dist/server/relayerHandler.cjs +187 -25
- package/dist/server/relayerHandler.cjs.map +1 -1
- package/dist/server/relayerHandler.d.ts +35 -4
- package/dist/server/relayerHandler.js +187 -25
- package/dist/server/relayerHandler.js.map +1 -1
- package/dist/storage/index.cjs +3 -0
- package/dist/storage/index.cjs.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/providers/dropbox.cjs +237 -0
- package/dist/storage/providers/dropbox.cjs.map +1 -0
- package/dist/storage/providers/dropbox.d.ts +39 -0
- package/dist/storage/providers/dropbox.js +215 -0
- package/dist/storage/providers/dropbox.js.map +1 -0
- package/dist/storage/providers/dropbox.test.d.ts +1 -0
- package/dist/tests/data-upload-owner-validation.test.d.ts +1 -0
- package/dist/types/atomicStore.cjs +31 -0
- package/dist/types/atomicStore.cjs.map +1 -0
- package/dist/types/atomicStore.d.ts +236 -0
- package/dist/types/atomicStore.js +7 -0
- package/dist/types/atomicStore.js.map +1 -0
- package/dist/types/config.cjs.map +1 -1
- package/dist/types/config.d.ts +3 -3
- package/dist/types/config.js.map +1 -1
- package/dist/types/controller-context.cjs.map +1 -1
- package/dist/types/controller-context.d.ts +4 -3
- package/dist/types/data.cjs.map +1 -1
- package/dist/types/data.d.ts +7 -4
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/operationStore.cjs +17 -0
- package/dist/types/operationStore.cjs.map +1 -0
- package/dist/types/operationStore.d.ts +171 -0
- package/dist/types/operationStore.js +1 -0
- package/dist/types/operationStore.js.map +1 -0
- package/dist/types/operations.cjs +3 -15
- package/dist/types/operations.cjs.map +1 -1
- package/dist/types/operations.d.ts +17 -88
- package/dist/types/operations.js +2 -13
- package/dist/types/operations.js.map +1 -1
- package/dist/types/options.cjs +17 -0
- package/dist/types/options.cjs.map +1 -0
- package/dist/types/options.d.ts +308 -0
- package/dist/types/options.js +1 -0
- package/dist/types/options.js.map +1 -0
- package/dist/types/permissions.cjs.map +1 -1
- package/dist/types/permissions.d.ts +4 -0
- package/dist/types/personal.cjs.map +1 -1
- package/dist/types/personal.d.ts +19 -0
- package/dist/types/relayer.cjs.map +1 -1
- package/dist/types/relayer.d.ts +10 -10
- package/dist/types/utils.cjs.map +1 -1
- package/dist/types/utils.d.ts +0 -49
- package/dist/utils/__tests__/chainQuery.test.d.ts +1 -0
- package/dist/utils/__tests__/subgraphConsistency.test.d.ts +4 -0
- package/dist/utils/__tests__/subgraphPagination.test.d.ts +4 -0
- package/dist/utils/chainQuery.cjs +107 -0
- package/dist/utils/chainQuery.cjs.map +1 -0
- package/dist/utils/chainQuery.d.ts +31 -0
- package/dist/utils/chainQuery.js +82 -0
- package/dist/utils/chainQuery.js.map +1 -0
- package/dist/utils/grantFiles.cjs +4 -1
- package/dist/utils/grantFiles.cjs.map +1 -1
- package/dist/utils/grantFiles.js +4 -1
- package/dist/utils/grantFiles.js.map +1 -1
- package/dist/utils/subgraphConsistency.cjs +184 -0
- package/dist/utils/subgraphConsistency.cjs.map +1 -0
- package/dist/utils/subgraphConsistency.d.ts +65 -0
- package/dist/utils/subgraphConsistency.js +155 -0
- package/dist/utils/subgraphConsistency.js.map +1 -0
- package/dist/utils/subgraphMetaCache.cjs +101 -0
- package/dist/utils/subgraphMetaCache.cjs.map +1 -0
- package/dist/utils/subgraphMetaCache.d.ts +56 -0
- package/dist/utils/subgraphMetaCache.js +76 -0
- package/dist/utils/subgraphMetaCache.js.map +1 -0
- package/dist/utils/subgraphPagination.cjs +104 -0
- package/dist/utils/subgraphPagination.cjs.map +1 -0
- package/dist/utils/subgraphPagination.d.ts +78 -0
- package/dist/utils/subgraphPagination.js +78 -0
- package/dist/utils/subgraphPagination.js.map +1 -0
- package/package.json +1 -1
|
@@ -33,6 +33,7 @@ __export(permissions_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(permissions_exports);
|
|
34
34
|
var import_viem = require("viem");
|
|
35
35
|
var import_multicall = require("../utils/multicall");
|
|
36
|
+
var import_pollingManager = require("../core/pollingManager");
|
|
36
37
|
var import_errors = require("../errors");
|
|
37
38
|
var import_addresses = require("../config/addresses");
|
|
38
39
|
var import_abi = require("../generated/abi");
|
|
@@ -214,7 +215,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
214
215
|
if (response.type === "error") {
|
|
215
216
|
throw new Error(response.error);
|
|
216
217
|
}
|
|
217
|
-
if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
|
|
218
|
+
if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
|
|
218
219
|
grantUrl = response.result.url;
|
|
219
220
|
} else {
|
|
220
221
|
throw new Error("Invalid response from relayer for grant storage");
|
|
@@ -322,7 +323,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
322
323
|
if (response.type === "error") {
|
|
323
324
|
throw new Error(response.error);
|
|
324
325
|
}
|
|
325
|
-
if (response.type === "direct" && typeof response.result === "object" && "url" in response.result) {
|
|
326
|
+
if (response.type === "direct" && typeof response.result === "object" && response.result !== null && "url" in response.result) {
|
|
326
327
|
grantUrl = response.result.url;
|
|
327
328
|
} else {
|
|
328
329
|
throw new Error("Invalid response from relayer for grant storage");
|
|
@@ -421,7 +422,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
421
422
|
finalHash = response.hash;
|
|
422
423
|
} else if (response.type === "pending") {
|
|
423
424
|
const pollResult = await this.pollRelayerForConfirmation(
|
|
424
|
-
response.operationId
|
|
425
|
+
response.operationId,
|
|
426
|
+
options
|
|
425
427
|
);
|
|
426
428
|
finalHash = pollResult.hash;
|
|
427
429
|
} else if (response.type === "confirmed") {
|
|
@@ -543,7 +545,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
543
545
|
* const result = await txHandle.waitForEvents();
|
|
544
546
|
* ```
|
|
545
547
|
*/
|
|
546
|
-
async submitSignedAddAndTrustServer(typedData, signature,
|
|
548
|
+
async submitSignedAddAndTrustServer(typedData, signature, options) {
|
|
547
549
|
try {
|
|
548
550
|
const addAndTrustServerInput = {
|
|
549
551
|
nonce: BigInt(typedData.message.nonce),
|
|
@@ -553,7 +555,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
553
555
|
};
|
|
554
556
|
const hash = await this.submitAddAndTrustServerTransaction(
|
|
555
557
|
addAndTrustServerInput,
|
|
556
|
-
signature
|
|
558
|
+
signature,
|
|
559
|
+
options
|
|
557
560
|
);
|
|
558
561
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
559
562
|
const { tx } = await import("../utils/transactionHelpers");
|
|
@@ -651,34 +654,22 @@ class PermissionsController extends import_base.BaseController {
|
|
|
651
654
|
* Polls the relayer for confirmation of a pending operation.
|
|
652
655
|
*
|
|
653
656
|
* @param operationId - The operation ID to poll
|
|
654
|
-
* @
|
|
655
|
-
* @
|
|
657
|
+
* @param options - Polling configuration including status updates and cancellation
|
|
658
|
+
* @returns Promise resolving to the confirmed hash and receipt
|
|
659
|
+
* @throws {TransactionPendingError} When the operation times out
|
|
660
|
+
* @throws {Error} When the operation fails or is cancelled
|
|
656
661
|
* @internal
|
|
657
662
|
*/
|
|
658
|
-
async pollRelayerForConfirmation(operationId, options
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
const startTime = Date.now();
|
|
662
|
-
while (Date.now() - startTime < timeout) {
|
|
663
|
-
if (!this.context.relayer) {
|
|
664
|
-
throw new Error("Relayer not configured for polling");
|
|
665
|
-
}
|
|
666
|
-
const statusResponse = await this.context.relayer({
|
|
667
|
-
type: "status_check",
|
|
668
|
-
operationId
|
|
669
|
-
});
|
|
670
|
-
if (statusResponse.type === "confirmed") {
|
|
671
|
-
return { hash: statusResponse.hash };
|
|
672
|
-
}
|
|
673
|
-
if (statusResponse.type === "error") {
|
|
674
|
-
throw new Error(
|
|
675
|
-
`Operation ${operationId} failed: ${statusResponse.error}`
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
679
|
-
interval = Math.min(interval * 1.5, 5e3);
|
|
663
|
+
async pollRelayerForConfirmation(operationId, options) {
|
|
664
|
+
if (!this.context.relayer) {
|
|
665
|
+
throw new Error("Relayer not configured for polling");
|
|
680
666
|
}
|
|
681
|
-
|
|
667
|
+
const pollingManager = new import_pollingManager.PollingManager(this.context.relayer);
|
|
668
|
+
return await pollingManager.startPolling(operationId, {
|
|
669
|
+
signal: options?.signal,
|
|
670
|
+
onStatusUpdate: options?.onStatusUpdate,
|
|
671
|
+
...options?.pollingOptions
|
|
672
|
+
});
|
|
682
673
|
}
|
|
683
674
|
/**
|
|
684
675
|
* Submits an already-signed permission revoke transaction to the blockchain.
|
|
@@ -701,7 +692,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
701
692
|
* const result = await txHandle.waitForEvents();
|
|
702
693
|
* ```
|
|
703
694
|
*/
|
|
704
|
-
async submitSignedRevoke(typedData, signature,
|
|
695
|
+
async submitSignedRevoke(typedData, signature, options) {
|
|
705
696
|
try {
|
|
706
697
|
let hash;
|
|
707
698
|
if (this.context.relayer) {
|
|
@@ -719,7 +710,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
719
710
|
hash = response.hash;
|
|
720
711
|
} else if (response.type === "pending") {
|
|
721
712
|
const pollResult = await this.pollRelayerForConfirmation(
|
|
722
|
-
response.operationId
|
|
713
|
+
response.operationId,
|
|
714
|
+
options
|
|
723
715
|
);
|
|
724
716
|
hash = pollResult.hash;
|
|
725
717
|
} else if (response.type === "confirmed") {
|
|
@@ -734,7 +726,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
734
726
|
} else {
|
|
735
727
|
hash = await this.submitDirectRevokeTransaction(
|
|
736
728
|
typedData,
|
|
737
|
-
signature
|
|
729
|
+
signature,
|
|
730
|
+
options
|
|
738
731
|
);
|
|
739
732
|
}
|
|
740
733
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
@@ -776,7 +769,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
776
769
|
* const result = await txHandle.waitForEvents();
|
|
777
770
|
* ```
|
|
778
771
|
*/
|
|
779
|
-
async submitSignedUntrustServer(typedData, signature,
|
|
772
|
+
async submitSignedUntrustServer(typedData, signature, options) {
|
|
780
773
|
try {
|
|
781
774
|
let hash;
|
|
782
775
|
if (this.context.relayer) {
|
|
@@ -787,7 +780,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
787
780
|
signature,
|
|
788
781
|
expectedUserAddress: this.context.userAddress
|
|
789
782
|
});
|
|
790
|
-
if (response.type === "
|
|
783
|
+
if (response.type === "submitted") {
|
|
784
|
+
hash = response.hash;
|
|
785
|
+
} else if (response.type === "signed") {
|
|
791
786
|
hash = response.hash;
|
|
792
787
|
} else if (response.type === "error") {
|
|
793
788
|
throw new Error(`Relayer error: ${response.error}`);
|
|
@@ -799,7 +794,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
799
794
|
} else {
|
|
800
795
|
hash = await this.submitSignedUntrustTransaction(
|
|
801
796
|
typedData,
|
|
802
|
-
signature
|
|
797
|
+
signature,
|
|
798
|
+
options
|
|
803
799
|
);
|
|
804
800
|
}
|
|
805
801
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
@@ -1021,7 +1017,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1021
1017
|
* console.log(`Permission ${result.permissionId} revoked`);
|
|
1022
1018
|
* ```
|
|
1023
1019
|
*/
|
|
1024
|
-
async submitRevokeWithSignature(params) {
|
|
1020
|
+
async submitRevokeWithSignature(params, options) {
|
|
1025
1021
|
this.assertWallet();
|
|
1026
1022
|
try {
|
|
1027
1023
|
if (!this.context.walletClient?.chain?.id) {
|
|
@@ -1053,7 +1049,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1053
1049
|
signature,
|
|
1054
1050
|
expectedUserAddress: this.context.userAddress
|
|
1055
1051
|
});
|
|
1056
|
-
if (response.type === "
|
|
1052
|
+
if (response.type === "submitted") {
|
|
1053
|
+
hash = response.hash;
|
|
1054
|
+
} else if (response.type === "signed") {
|
|
1057
1055
|
hash = response.hash;
|
|
1058
1056
|
} else if (response.type === "error") {
|
|
1059
1057
|
throw new Error(`Relayer error: ${response.error}`);
|
|
@@ -1065,7 +1063,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1065
1063
|
} else {
|
|
1066
1064
|
hash = await this.submitDirectRevokeTransaction(
|
|
1067
1065
|
typedData,
|
|
1068
|
-
signature
|
|
1066
|
+
signature,
|
|
1067
|
+
options
|
|
1069
1068
|
);
|
|
1070
1069
|
}
|
|
1071
1070
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
@@ -1391,7 +1390,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1391
1390
|
* ```
|
|
1392
1391
|
*/
|
|
1393
1392
|
async getUserPermissionGrantsOnChain(options = {}) {
|
|
1394
|
-
const { limit = 50, subgraphUrl } = options;
|
|
1393
|
+
const { limit = 50, fetchAll = false, subgraphUrl } = options;
|
|
1394
|
+
const pageSize = fetchAll ? 100 : limit;
|
|
1395
|
+
const maxResults = fetchAll ? 1e4 : limit;
|
|
1395
1396
|
try {
|
|
1396
1397
|
const userAddress = this.context.userAddress;
|
|
1397
1398
|
const graphqlEndpoint = subgraphUrl ?? this.context.subgraphUrl;
|
|
@@ -1401,10 +1402,10 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1401
1402
|
);
|
|
1402
1403
|
}
|
|
1403
1404
|
const query = `
|
|
1404
|
-
query GetUserPermissions($userId: ID!) {
|
|
1405
|
+
query GetUserPermissions($userId: ID!, $first: Int!, $skip: Int!) {
|
|
1405
1406
|
user(id: $userId) {
|
|
1406
1407
|
id
|
|
1407
|
-
permissions {
|
|
1408
|
+
permissions(first: $first, skip: $skip, orderBy: addedAtBlock, orderDirection: desc) {
|
|
1408
1409
|
id
|
|
1409
1410
|
grant
|
|
1410
1411
|
nonce
|
|
@@ -1422,34 +1423,82 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1422
1423
|
}
|
|
1423
1424
|
}
|
|
1424
1425
|
`;
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1426
|
+
const allPermissions = [];
|
|
1427
|
+
let currentOffset = 0;
|
|
1428
|
+
if (!fetchAll) {
|
|
1429
|
+
const response = await fetch(graphqlEndpoint, {
|
|
1430
|
+
method: "POST",
|
|
1431
|
+
headers: {
|
|
1432
|
+
"Content-Type": "application/json"
|
|
1433
|
+
},
|
|
1434
|
+
body: JSON.stringify({
|
|
1435
|
+
query,
|
|
1436
|
+
variables: {
|
|
1437
|
+
userId: userAddress.toLowerCase(),
|
|
1438
|
+
first: limit,
|
|
1439
|
+
skip: 0
|
|
1440
|
+
}
|
|
1441
|
+
})
|
|
1442
|
+
});
|
|
1443
|
+
if (!response.ok) {
|
|
1444
|
+
throw new import_errors.BlockchainError(
|
|
1445
|
+
`Subgraph request failed: ${response.status} ${response.statusText}`
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
const result = await response.json();
|
|
1449
|
+
if (result.errors) {
|
|
1450
|
+
throw new import_errors.BlockchainError(
|
|
1451
|
+
`Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
const userData = result.data?.user;
|
|
1455
|
+
if (!userData?.permissions?.length) {
|
|
1456
|
+
return [];
|
|
1457
|
+
}
|
|
1458
|
+
allPermissions.push(...userData.permissions);
|
|
1459
|
+
} else {
|
|
1460
|
+
while (allPermissions.length < maxResults) {
|
|
1461
|
+
const currentLimit = Math.min(
|
|
1462
|
+
pageSize,
|
|
1463
|
+
maxResults - allPermissions.length
|
|
1464
|
+
);
|
|
1465
|
+
const response = await fetch(graphqlEndpoint, {
|
|
1466
|
+
method: "POST",
|
|
1467
|
+
headers: {
|
|
1468
|
+
"Content-Type": "application/json"
|
|
1469
|
+
},
|
|
1470
|
+
body: JSON.stringify({
|
|
1471
|
+
query,
|
|
1472
|
+
variables: {
|
|
1473
|
+
userId: userAddress.toLowerCase(),
|
|
1474
|
+
first: currentLimit,
|
|
1475
|
+
skip: currentOffset
|
|
1476
|
+
}
|
|
1477
|
+
})
|
|
1478
|
+
});
|
|
1479
|
+
if (!response.ok) {
|
|
1480
|
+
throw new import_errors.BlockchainError(
|
|
1481
|
+
`Subgraph request failed: ${response.status} ${response.statusText}`
|
|
1482
|
+
);
|
|
1434
1483
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1484
|
+
const result = await response.json();
|
|
1485
|
+
if (result.errors) {
|
|
1486
|
+
throw new import_errors.BlockchainError(
|
|
1487
|
+
`Subgraph errors: ${result.errors.map((e) => e.message).join(", ")}`
|
|
1488
|
+
);
|
|
1489
|
+
}
|
|
1490
|
+
const userData = result.data?.user;
|
|
1491
|
+
if (!userData?.permissions?.length) {
|
|
1492
|
+
break;
|
|
1493
|
+
}
|
|
1494
|
+
allPermissions.push(...userData.permissions);
|
|
1495
|
+
if (userData.permissions.length < currentLimit) {
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
currentOffset += userData.permissions.length;
|
|
1499
|
+
}
|
|
1451
1500
|
}
|
|
1452
|
-
const onChainGrants =
|
|
1501
|
+
const onChainGrants = allPermissions.map(
|
|
1453
1502
|
(permission) => ({
|
|
1454
1503
|
id: BigInt(permission.id),
|
|
1455
1504
|
grantUrl: permission.grant,
|
|
@@ -1630,7 +1679,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1630
1679
|
* @param params - Parameters for adding and trusting the server
|
|
1631
1680
|
* @returns Promise resolving to TransactionResult with ServerTrustResult event data
|
|
1632
1681
|
*/
|
|
1633
|
-
async submitAddAndTrustServerWithSignature(params) {
|
|
1682
|
+
async submitAddAndTrustServerWithSignature(params, options) {
|
|
1634
1683
|
this.assertWallet();
|
|
1635
1684
|
try {
|
|
1636
1685
|
const nonce = await this.getServersUserNonce();
|
|
@@ -1666,7 +1715,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1666
1715
|
if (response.type === "error") {
|
|
1667
1716
|
throw new import_errors.RelayerError(response.error);
|
|
1668
1717
|
}
|
|
1669
|
-
if (response.type === "
|
|
1718
|
+
if (response.type === "submitted") {
|
|
1719
|
+
hash = response.hash;
|
|
1720
|
+
} else if (response.type === "signed") {
|
|
1670
1721
|
hash = response.hash;
|
|
1671
1722
|
} else {
|
|
1672
1723
|
throw new Error("Unexpected response type from relayer");
|
|
@@ -1674,7 +1725,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1674
1725
|
} else {
|
|
1675
1726
|
hash = await this.submitAddAndTrustServerTransaction(
|
|
1676
1727
|
addAndTrustServerInput,
|
|
1677
|
-
signature
|
|
1728
|
+
signature,
|
|
1729
|
+
options
|
|
1678
1730
|
);
|
|
1679
1731
|
}
|
|
1680
1732
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
@@ -1713,7 +1765,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1713
1765
|
* @throws {ServerUrlMismatchError} When server URL doesn't match existing registration
|
|
1714
1766
|
* @throws {BlockchainError} When trust operation fails for any other reason
|
|
1715
1767
|
*/
|
|
1716
|
-
async submitTrustServerWithSignature(params) {
|
|
1768
|
+
async submitTrustServerWithSignature(params, options) {
|
|
1717
1769
|
this.assertWallet();
|
|
1718
1770
|
try {
|
|
1719
1771
|
const nonce = await this.getServersUserNonce();
|
|
@@ -1735,7 +1787,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1735
1787
|
if (response.type === "error") {
|
|
1736
1788
|
throw new import_errors.RelayerError(response.error);
|
|
1737
1789
|
}
|
|
1738
|
-
if (response.type === "
|
|
1790
|
+
if (response.type === "submitted") {
|
|
1791
|
+
hash = response.hash;
|
|
1792
|
+
} else if (response.type === "signed") {
|
|
1739
1793
|
hash = response.hash;
|
|
1740
1794
|
} else {
|
|
1741
1795
|
throw new Error("Unexpected response type from relayer");
|
|
@@ -1743,7 +1797,8 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1743
1797
|
} else {
|
|
1744
1798
|
hash = await this.submitTrustServerTransaction(
|
|
1745
1799
|
trustServerInput,
|
|
1746
|
-
signature
|
|
1800
|
+
signature,
|
|
1801
|
+
options
|
|
1747
1802
|
);
|
|
1748
1803
|
}
|
|
1749
1804
|
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
@@ -1905,7 +1960,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
1905
1960
|
if (response.type === "error") {
|
|
1906
1961
|
throw new import_errors.RelayerError(response.error);
|
|
1907
1962
|
}
|
|
1908
|
-
if (response.type === "
|
|
1963
|
+
if (response.type === "submitted") {
|
|
1964
|
+
hash = response.hash;
|
|
1965
|
+
} else if (response.type === "signed") {
|
|
1909
1966
|
hash = response.hash;
|
|
1910
1967
|
} else {
|
|
1911
1968
|
throw new Error("Unexpected response type from relayer");
|
|
@@ -2351,7 +2408,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2351
2408
|
* @param signature - The cryptographic signature for the transaction
|
|
2352
2409
|
* @returns Promise resolving to the transaction hash
|
|
2353
2410
|
*/
|
|
2354
|
-
async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature) {
|
|
2411
|
+
async submitAddAndTrustServerTransaction(addAndTrustServerInput, signature, options) {
|
|
2355
2412
|
this.assertWallet();
|
|
2356
2413
|
const chainId = await this.context.walletClient.getChainId();
|
|
2357
2414
|
const DataPortabilityServersAddress = (0, import_addresses.getContractAddress)(
|
|
@@ -2385,7 +2442,16 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2385
2442
|
formattedSignature
|
|
2386
2443
|
],
|
|
2387
2444
|
account: this.context.walletClient?.account ?? this.context.userAddress,
|
|
2388
|
-
chain: this.context.walletClient?.chain ?? null
|
|
2445
|
+
chain: this.context.walletClient?.chain ?? null,
|
|
2446
|
+
...options && {
|
|
2447
|
+
gas: options.gas,
|
|
2448
|
+
nonce: options.nonce,
|
|
2449
|
+
// Use EIP-1559 gas pricing if available, otherwise legacy
|
|
2450
|
+
...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
|
|
2451
|
+
maxFeePerGas: options.maxFeePerGas,
|
|
2452
|
+
maxPriorityFeePerGas: options.maxPriorityFeePerGas
|
|
2453
|
+
} : options.gasPrice ? { gasPrice: options.gasPrice } : {}
|
|
2454
|
+
}
|
|
2389
2455
|
});
|
|
2390
2456
|
return txHash;
|
|
2391
2457
|
}
|
|
@@ -2429,7 +2495,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2429
2495
|
* @param signature - The cryptographic signature authorizing the revoke
|
|
2430
2496
|
* @returns Promise resolving to the transaction hash
|
|
2431
2497
|
*/
|
|
2432
|
-
async submitDirectRevokeTransaction(typedData, signature) {
|
|
2498
|
+
async submitDirectRevokeTransaction(typedData, signature, options) {
|
|
2433
2499
|
this.assertWallet();
|
|
2434
2500
|
const chainId = await this.context.walletClient.getChainId();
|
|
2435
2501
|
const DataPortabilityPermissionsAddress = (0, import_addresses.getContractAddress)(
|
|
@@ -2444,7 +2510,16 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2444
2510
|
functionName: "revokePermissionWithSignature",
|
|
2445
2511
|
args: [typedData.message, formattedSignature],
|
|
2446
2512
|
account: this.context.walletClient?.account ?? this.context.userAddress,
|
|
2447
|
-
chain: this.context.walletClient?.chain ?? null
|
|
2513
|
+
chain: this.context.walletClient?.chain ?? null,
|
|
2514
|
+
...options && {
|
|
2515
|
+
gas: options.gas,
|
|
2516
|
+
nonce: options.nonce,
|
|
2517
|
+
// Use EIP-1559 gas pricing if available, otherwise legacy
|
|
2518
|
+
...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
|
|
2519
|
+
maxFeePerGas: options.maxFeePerGas,
|
|
2520
|
+
maxPriorityFeePerGas: options.maxPriorityFeePerGas
|
|
2521
|
+
} : options.gasPrice ? { gasPrice: options.gasPrice } : {}
|
|
2522
|
+
}
|
|
2448
2523
|
});
|
|
2449
2524
|
return txHash;
|
|
2450
2525
|
}
|
|
@@ -2455,7 +2530,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2455
2530
|
* @param signature - The cryptographic signature authorizing the untrust
|
|
2456
2531
|
* @returns Promise resolving to the transaction hash
|
|
2457
2532
|
*/
|
|
2458
|
-
async submitSignedUntrustTransaction(typedData, signature,
|
|
2533
|
+
async submitSignedUntrustTransaction(typedData, signature, options) {
|
|
2459
2534
|
this.assertWallet();
|
|
2460
2535
|
const chainId = await this.context.walletClient.getChainId();
|
|
2461
2536
|
const DataPortabilityServersAddress = (0, import_addresses.getContractAddress)(
|
|
@@ -2474,7 +2549,16 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2474
2549
|
functionName: "untrustServerWithSignature",
|
|
2475
2550
|
args: [contractMessage, formattedSignature],
|
|
2476
2551
|
account: this.context.walletClient?.account ?? this.context.userAddress,
|
|
2477
|
-
chain: this.context.walletClient?.chain ?? null
|
|
2552
|
+
chain: this.context.walletClient?.chain ?? null,
|
|
2553
|
+
...options && {
|
|
2554
|
+
gas: options.gas,
|
|
2555
|
+
nonce: options.nonce,
|
|
2556
|
+
// Use EIP-1559 gas pricing if available, otherwise legacy
|
|
2557
|
+
...options.maxFeePerGas || options.maxPriorityFeePerGas ? {
|
|
2558
|
+
maxFeePerGas: options.maxFeePerGas,
|
|
2559
|
+
maxPriorityFeePerGas: options.maxPriorityFeePerGas
|
|
2560
|
+
} : options.gasPrice ? { gasPrice: options.gasPrice } : {}
|
|
2561
|
+
}
|
|
2478
2562
|
});
|
|
2479
2563
|
return txHash;
|
|
2480
2564
|
}
|
|
@@ -2487,6 +2571,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2487
2571
|
* A grantee is an entity (like an application) that can receive data permissions
|
|
2488
2572
|
* from users. Once registered, users can grant the grantee access to their data.
|
|
2489
2573
|
*
|
|
2574
|
+
* This method supports gasless transactions via relayer when configured.
|
|
2575
|
+
* If no relayer is available, it falls back to direct wallet transactions.
|
|
2576
|
+
*
|
|
2490
2577
|
* @param params - Parameters for registering the grantee
|
|
2491
2578
|
* @param params.owner - The Ethereum address that will own this grantee registration
|
|
2492
2579
|
* @param params.granteeAddress - The Ethereum address of the grantee (application)
|
|
@@ -2495,7 +2582,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2495
2582
|
* @returns Promise resolving to the transaction hash
|
|
2496
2583
|
* @throws {BlockchainError} When the grantee registration transaction fails
|
|
2497
2584
|
* @throws {UserRejectedRequestError} When user rejects the transaction
|
|
2498
|
-
* @throws {
|
|
2585
|
+
* @throws {RelayerError} When gasless transaction submission fails
|
|
2499
2586
|
*
|
|
2500
2587
|
* @example
|
|
2501
2588
|
* ```typescript
|
|
@@ -2508,36 +2595,87 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2508
2595
|
* ```
|
|
2509
2596
|
*/
|
|
2510
2597
|
async submitRegisterGrantee(params, options) {
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2598
|
+
try {
|
|
2599
|
+
let hash;
|
|
2600
|
+
if (this.context.relayer) {
|
|
2601
|
+
const request = {
|
|
2602
|
+
type: "direct",
|
|
2603
|
+
operation: "submitRegisterGrantee",
|
|
2604
|
+
params: {
|
|
2605
|
+
owner: params.owner,
|
|
2606
|
+
granteeAddress: params.granteeAddress,
|
|
2607
|
+
publicKey: params.publicKey
|
|
2608
|
+
}
|
|
2609
|
+
};
|
|
2610
|
+
const response = await this.context.relayer(request);
|
|
2611
|
+
if (response.type === "error") {
|
|
2612
|
+
throw new import_errors.RelayerError(response.error);
|
|
2613
|
+
}
|
|
2614
|
+
if (response.type === "submitted") {
|
|
2615
|
+
hash = response.hash;
|
|
2616
|
+
} else if (response.type === "direct") {
|
|
2617
|
+
const result = response.result;
|
|
2618
|
+
hash = result.transactionHash;
|
|
2619
|
+
} else {
|
|
2620
|
+
throw new Error("Unexpected response type from relayer");
|
|
2621
|
+
}
|
|
2622
|
+
} else {
|
|
2623
|
+
this.assertWallet();
|
|
2624
|
+
const chainId = await this.context.walletClient.getChainId();
|
|
2625
|
+
const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
|
|
2626
|
+
chainId,
|
|
2627
|
+
"DataPortabilityGrantees"
|
|
2628
|
+
);
|
|
2629
|
+
const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
|
|
2630
|
+
const ownerAddress = (0, import_viem.getAddress)(params.owner);
|
|
2631
|
+
const granteeAddress = (0, import_viem.getAddress)(params.granteeAddress);
|
|
2632
|
+
const account2 = this.context.walletClient?.account ?? this.context.userAddress;
|
|
2633
|
+
hash = await this.context.walletClient.writeContract({
|
|
2634
|
+
address: DataPortabilityGranteesAddress,
|
|
2635
|
+
abi: DataPortabilityGranteesAbi,
|
|
2636
|
+
functionName: "registerGrantee",
|
|
2637
|
+
args: [ownerAddress, granteeAddress, params.publicKey],
|
|
2638
|
+
account: account2,
|
|
2639
|
+
chain: this.context.walletClient?.chain ?? null,
|
|
2640
|
+
...this.spreadTransactionOptions(options)
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
const account = this.context.walletClient?.account ?? this.context.userAddress;
|
|
2644
|
+
const { tx } = await import("../utils/transactionHelpers");
|
|
2645
|
+
return tx({
|
|
2646
|
+
hash,
|
|
2647
|
+
from: typeof account === "string" ? account : account.address,
|
|
2648
|
+
contract: "DataPortabilityGrantees",
|
|
2649
|
+
fn: "registerGrantee"
|
|
2650
|
+
});
|
|
2651
|
+
} catch (error) {
|
|
2652
|
+
if (error instanceof Error) {
|
|
2653
|
+
if (error instanceof import_errors.RelayerError || error instanceof import_errors.UserRejectedRequestError || error instanceof import_errors.SerializationError || error instanceof import_errors.SignatureError || error instanceof import_errors.BlockchainError) {
|
|
2654
|
+
throw error;
|
|
2655
|
+
}
|
|
2656
|
+
if (error.name === "ContractFunctionExecutionError") {
|
|
2657
|
+
throw new import_errors.BlockchainError(
|
|
2658
|
+
`Grantee registration failed: ${error.message}`,
|
|
2659
|
+
error
|
|
2660
|
+
);
|
|
2661
|
+
}
|
|
2662
|
+
if (error.name === "UserRejectedRequestError") {
|
|
2663
|
+
throw new import_errors.UserRejectedRequestError(
|
|
2664
|
+
"User rejected the grantee registration transaction"
|
|
2665
|
+
);
|
|
2666
|
+
}
|
|
2667
|
+
throw new import_errors.BlockchainError(
|
|
2668
|
+
`Failed to register grantee: ${error.message}`,
|
|
2669
|
+
error
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
throw new import_errors.BlockchainError(`Failed to register grantee: ${String(error)}`);
|
|
2673
|
+
}
|
|
2537
2674
|
}
|
|
2538
2675
|
// TODO: When DataPortabilityGrantees contract adds registerGranteeWithSignature function,
|
|
2539
2676
|
// implement submitRegisterGranteeWithSignature and submitSignedRegisterGrantee methods
|
|
2540
|
-
// to support gasless transactions via relayer
|
|
2677
|
+
// to support EIP-712 signed gasless transactions via relayer.
|
|
2678
|
+
// Current implementation above supports direct gasless transactions (relayer pays gas directly).
|
|
2541
2679
|
/**
|
|
2542
2680
|
* Retrieves all registered grantees from the DataPortabilityGrantees contract.
|
|
2543
2681
|
*
|
|
@@ -2585,27 +2723,52 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2585
2723
|
const total = Number(totalCount);
|
|
2586
2724
|
const limit = options.limit ?? 50;
|
|
2587
2725
|
const offset = options.offset ?? 0;
|
|
2588
|
-
const
|
|
2589
|
-
const
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2726
|
+
const includePermissions = options.includePermissions ?? true;
|
|
2727
|
+
const startId = total - offset;
|
|
2728
|
+
const endId = Math.max(startId - limit + 1, 1);
|
|
2729
|
+
const granteeIds = Array.from(
|
|
2730
|
+
{ length: startId - endId + 1 },
|
|
2731
|
+
(_, i) => startId - i
|
|
2732
|
+
// Generate IDs in descending order
|
|
2733
|
+
);
|
|
2734
|
+
let grantees;
|
|
2735
|
+
if (includePermissions) {
|
|
2736
|
+
const granteePromises = granteeIds.map(
|
|
2737
|
+
(granteeId) => this.getGranteeById(granteeId)
|
|
2738
|
+
);
|
|
2739
|
+
const granteeResults = await Promise.all(granteePromises);
|
|
2740
|
+
grantees = granteeResults.filter(
|
|
2741
|
+
(grantee) => grantee !== null
|
|
2742
|
+
);
|
|
2743
|
+
} else {
|
|
2744
|
+
const granteeInfoPromises = granteeIds.map(
|
|
2745
|
+
async (granteeId) => {
|
|
2746
|
+
try {
|
|
2747
|
+
const granteeInfo = await this.context.publicClient.readContract({
|
|
2748
|
+
address: DataPortabilityGranteesAddress,
|
|
2749
|
+
abi: DataPortabilityGranteesAbi,
|
|
2750
|
+
functionName: "granteesV2",
|
|
2751
|
+
args: [BigInt(granteeId)]
|
|
2752
|
+
});
|
|
2753
|
+
const grantee = {
|
|
2754
|
+
id: granteeId,
|
|
2755
|
+
owner: granteeInfo.owner,
|
|
2756
|
+
address: granteeInfo.granteeAddress,
|
|
2757
|
+
publicKey: granteeInfo.publicKey,
|
|
2758
|
+
permissionIds: []
|
|
2759
|
+
// TypeScript infers number[] from Grantee type
|
|
2760
|
+
};
|
|
2761
|
+
return grantee;
|
|
2762
|
+
} catch (error) {
|
|
2763
|
+
console.warn(`Failed to fetch grantee ${granteeId}:`, error);
|
|
2764
|
+
return null;
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
);
|
|
2768
|
+
const granteeInfoResults = await Promise.all(granteeInfoPromises);
|
|
2769
|
+
grantees = granteeInfoResults.filter(
|
|
2770
|
+
(grantee) => grantee !== null
|
|
2771
|
+
);
|
|
2609
2772
|
}
|
|
2610
2773
|
return {
|
|
2611
2774
|
grantees,
|
|
@@ -2616,15 +2779,16 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2616
2779
|
};
|
|
2617
2780
|
}
|
|
2618
2781
|
/**
|
|
2619
|
-
* Retrieves a specific grantee by their Ethereum address
|
|
2782
|
+
* Retrieves a specific grantee by their Ethereum wallet address.
|
|
2620
2783
|
*
|
|
2784
|
+
* @remarks
|
|
2621
2785
|
* Looks up a registered grantee (application) using their Ethereum address
|
|
2622
|
-
* and returns their complete registration information including permissions.
|
|
2786
|
+
* and returns their complete registration information including all associated permissions.
|
|
2623
2787
|
*
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2626
|
-
* @
|
|
2627
|
-
* @
|
|
2788
|
+
* Returns `null` if the address is not registered as a grantee or if an error occurs.
|
|
2789
|
+
*
|
|
2790
|
+
* @param granteeAddress - Ethereum wallet address of the grantee to query
|
|
2791
|
+
* @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
|
|
2628
2792
|
*
|
|
2629
2793
|
* @example
|
|
2630
2794
|
* ```typescript
|
|
@@ -2649,40 +2813,32 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2649
2813
|
);
|
|
2650
2814
|
const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
|
|
2651
2815
|
try {
|
|
2652
|
-
const granteeInfo = await this.context.publicClient.readContract({
|
|
2653
|
-
address: DataPortabilityGranteesAddress,
|
|
2654
|
-
abi: DataPortabilityGranteesAbi,
|
|
2655
|
-
functionName: "granteeByAddress",
|
|
2656
|
-
args: [granteeAddress]
|
|
2657
|
-
});
|
|
2658
2816
|
const granteeId = await this.context.publicClient.readContract({
|
|
2659
2817
|
address: DataPortabilityGranteesAddress,
|
|
2660
2818
|
abi: DataPortabilityGranteesAbi,
|
|
2661
2819
|
functionName: "granteeAddressToId",
|
|
2662
2820
|
args: [granteeAddress]
|
|
2663
2821
|
});
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
publicKey: granteeInfo.publicKey,
|
|
2669
|
-
permissionIds: granteeInfo.permissionIds.map((id) => Number(id))
|
|
2670
|
-
};
|
|
2822
|
+
if (granteeId === 0n) {
|
|
2823
|
+
return null;
|
|
2824
|
+
}
|
|
2825
|
+
return await this.getGranteeById(Number(granteeId));
|
|
2671
2826
|
} catch (error) {
|
|
2672
2827
|
console.warn(`Failed to fetch grantee ${granteeAddress}:`, error);
|
|
2673
2828
|
return null;
|
|
2674
2829
|
}
|
|
2675
2830
|
}
|
|
2676
2831
|
/**
|
|
2677
|
-
* Retrieves a specific grantee by their unique ID
|
|
2832
|
+
* Retrieves a specific grantee by their unique ID.
|
|
2678
2833
|
*
|
|
2834
|
+
* @remarks
|
|
2679
2835
|
* Looks up a registered grantee (application) using their numeric ID assigned during
|
|
2680
|
-
* registration and returns their complete information including permissions.
|
|
2836
|
+
* registration and returns their complete information including all associated permissions.
|
|
2681
2837
|
*
|
|
2682
|
-
*
|
|
2683
|
-
*
|
|
2684
|
-
* @
|
|
2685
|
-
* @
|
|
2838
|
+
* Returns `null` if the grantee is not found or if an error occurs during fetching.
|
|
2839
|
+
*
|
|
2840
|
+
* @param granteeId - Unique numeric ID of the grantee (1-indexed)
|
|
2841
|
+
* @returns Grantee information including ID, addresses, public key, and permission IDs, or `null` if not found
|
|
2686
2842
|
*
|
|
2687
2843
|
* @example
|
|
2688
2844
|
* ```typescript
|
|
@@ -2690,7 +2846,7 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2690
2846
|
*
|
|
2691
2847
|
* if (grantee) {
|
|
2692
2848
|
* console.log(`Grantee ID: ${grantee.id}`);
|
|
2693
|
-
* console.log(`Address: ${grantee.
|
|
2849
|
+
* console.log(`Address: ${grantee.address}`);
|
|
2694
2850
|
* console.log(`Owner: ${grantee.owner}`);
|
|
2695
2851
|
* console.log(`Total permissions: ${grantee.permissionIds.length}`);
|
|
2696
2852
|
* } else {
|
|
@@ -2706,18 +2862,23 @@ class PermissionsController extends import_base.BaseController {
|
|
|
2706
2862
|
);
|
|
2707
2863
|
const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
|
|
2708
2864
|
try {
|
|
2709
|
-
const
|
|
2865
|
+
const granteeInfoResult = await this.context.publicClient.readContract({
|
|
2710
2866
|
address: DataPortabilityGranteesAddress,
|
|
2711
2867
|
abi: DataPortabilityGranteesAbi,
|
|
2712
|
-
functionName: "
|
|
2868
|
+
functionName: "granteesV2",
|
|
2713
2869
|
args: [BigInt(granteeId)]
|
|
2714
2870
|
});
|
|
2871
|
+
const granteeInfo = granteeInfoResult;
|
|
2872
|
+
const allPermissionIdsResult = await this.getGranteePermissionsPaginated(
|
|
2873
|
+
BigInt(granteeId)
|
|
2874
|
+
);
|
|
2875
|
+
const allPermissionIds = allPermissionIdsResult;
|
|
2715
2876
|
return {
|
|
2716
2877
|
id: granteeId,
|
|
2717
2878
|
owner: granteeInfo.owner,
|
|
2718
2879
|
address: granteeInfo.granteeAddress,
|
|
2719
2880
|
publicKey: granteeInfo.publicKey,
|
|
2720
|
-
permissionIds:
|
|
2881
|
+
permissionIds: allPermissionIds.map((id) => Number(id))
|
|
2721
2882
|
};
|
|
2722
2883
|
} catch (error) {
|
|
2723
2884
|
console.warn(`Failed to fetch grantee ${granteeId}:`, error);
|
|
@@ -3114,6 +3275,31 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3114
3275
|
);
|
|
3115
3276
|
}
|
|
3116
3277
|
}
|
|
3278
|
+
/**
|
|
3279
|
+
* Retrieves detailed grant file data from IPFS or HTTP storage.
|
|
3280
|
+
*
|
|
3281
|
+
* @remarks
|
|
3282
|
+
* This method automatically uses the SDK's configured downloadRelayer to bypass CORS restrictions.
|
|
3283
|
+
* Use this instead of importing the standalone `retrieveGrantFile` utility.
|
|
3284
|
+
*
|
|
3285
|
+
* @param grantUrl - The grant file URL (from OnChainPermissionGrant.grantUrl)
|
|
3286
|
+
* @returns Promise resolving to the complete grant file with operation details
|
|
3287
|
+
* @throws {NetworkError} When all retrieval attempts fail
|
|
3288
|
+
* @example
|
|
3289
|
+
* ```typescript
|
|
3290
|
+
* const grants = await vana.permissions.getUserPermissionGrantsOnChain();
|
|
3291
|
+
* const grantFile = await vana.permissions.retrieveGrantFile(grants[0].grantUrl);
|
|
3292
|
+
* console.log(`Operation: ${grantFile.operation}`);
|
|
3293
|
+
* ```
|
|
3294
|
+
*/
|
|
3295
|
+
async retrieveGrantFile(grantUrl) {
|
|
3296
|
+
const { retrieveGrantFile: retrieveGrantFileUtil } = await import("../utils/grantFiles");
|
|
3297
|
+
return retrieveGrantFileUtil(
|
|
3298
|
+
grantUrl,
|
|
3299
|
+
void 0,
|
|
3300
|
+
this.context.downloadRelayer
|
|
3301
|
+
);
|
|
3302
|
+
}
|
|
3117
3303
|
/**
|
|
3118
3304
|
* Get all permissions for a specific file (alias for getFilePermissionIds)
|
|
3119
3305
|
*
|
|
@@ -3139,26 +3325,34 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3139
3325
|
// DATA PORTABILITY GRANTEES HELPER METHODS
|
|
3140
3326
|
// ===========================
|
|
3141
3327
|
/**
|
|
3142
|
-
*
|
|
3328
|
+
* Retrieves detailed grantee information including all associated permissions.
|
|
3329
|
+
*
|
|
3330
|
+
* @remarks
|
|
3331
|
+
* Returns grantee metadata and associated permission IDs. Uses the newer
|
|
3332
|
+
* paginated contract method internally for efficient permission fetching.
|
|
3333
|
+
*
|
|
3334
|
+
* @param granteeId - Unique grantee identifier as bigint
|
|
3335
|
+
* @returns Grantee information containing owner address, grantee address, public key, and permission IDs
|
|
3336
|
+
* @throws {BlockchainError} When grantee ID is not found or contract read fails
|
|
3143
3337
|
*
|
|
3144
|
-
* @
|
|
3145
|
-
*
|
|
3338
|
+
* @example
|
|
3339
|
+
* ```typescript
|
|
3340
|
+
* const granteeInfo = await vana.permissions.getGranteeInfo(BigInt(1));
|
|
3341
|
+
* console.log(`Grantee ${granteeInfo.granteeAddress} has ${granteeInfo.permissionIds.length} permissions`);
|
|
3342
|
+
* ```
|
|
3146
3343
|
*/
|
|
3147
3344
|
async getGranteeInfo(granteeId) {
|
|
3148
3345
|
try {
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
args: [granteeId]
|
|
3160
|
-
});
|
|
3161
|
-
return granteeInfo;
|
|
3346
|
+
const grantee = await this.getGranteeById(Number(granteeId));
|
|
3347
|
+
if (!grantee) {
|
|
3348
|
+
throw new Error("Grantee not found");
|
|
3349
|
+
}
|
|
3350
|
+
return {
|
|
3351
|
+
owner: grantee.owner,
|
|
3352
|
+
granteeAddress: grantee.address,
|
|
3353
|
+
publicKey: grantee.publicKey,
|
|
3354
|
+
permissionIds: grantee.permissionIds.map((id) => BigInt(id))
|
|
3355
|
+
};
|
|
3162
3356
|
} catch (error) {
|
|
3163
3357
|
throw new import_errors.BlockchainError(
|
|
3164
3358
|
`Failed to get grantee info: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
@@ -3167,10 +3361,21 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3167
3361
|
}
|
|
3168
3362
|
}
|
|
3169
3363
|
/**
|
|
3170
|
-
*
|
|
3364
|
+
* Retrieves detailed grantee information by wallet address.
|
|
3171
3365
|
*
|
|
3172
|
-
* @
|
|
3173
|
-
*
|
|
3366
|
+
* @remarks
|
|
3367
|
+
* Looks up the grantee ID from the provided address, then fetches complete
|
|
3368
|
+
* grantee information including all associated permissions.
|
|
3369
|
+
*
|
|
3370
|
+
* @param granteeAddress - Ethereum wallet address of the grantee to query
|
|
3371
|
+
* @returns Grantee information containing owner address, grantee address, public key, and permission IDs
|
|
3372
|
+
* @throws {BlockchainError} When grantee address is not registered or contract read fails
|
|
3373
|
+
*
|
|
3374
|
+
* @example
|
|
3375
|
+
* ```typescript
|
|
3376
|
+
* const granteeInfo = await vana.permissions.getGranteeInfoByAddress("0x742d35Cc6634c0532925a3b844Bc9e8e1ee3b2De");
|
|
3377
|
+
* console.log(`Found grantee with ${granteeInfo.permissionIds.length} permissions`);
|
|
3378
|
+
* ```
|
|
3174
3379
|
*/
|
|
3175
3380
|
async getGranteeInfoByAddress(granteeAddress) {
|
|
3176
3381
|
try {
|
|
@@ -3180,13 +3385,26 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3180
3385
|
"DataPortabilityGrantees"
|
|
3181
3386
|
);
|
|
3182
3387
|
const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
|
|
3183
|
-
const
|
|
3388
|
+
const granteeIdResult = await this.context.publicClient.readContract({
|
|
3184
3389
|
address: DataPortabilityGranteesAddress,
|
|
3185
3390
|
abi: DataPortabilityGranteesAbi,
|
|
3186
|
-
functionName: "
|
|
3391
|
+
functionName: "granteeAddressToId",
|
|
3187
3392
|
args: [granteeAddress]
|
|
3188
3393
|
});
|
|
3189
|
-
|
|
3394
|
+
const granteeId = granteeIdResult;
|
|
3395
|
+
if (granteeId === 0n) {
|
|
3396
|
+
throw new Error("Grantee not found");
|
|
3397
|
+
}
|
|
3398
|
+
const grantee = await this.getGranteeById(Number(granteeId));
|
|
3399
|
+
if (!grantee) {
|
|
3400
|
+
throw new Error("Grantee not found");
|
|
3401
|
+
}
|
|
3402
|
+
return {
|
|
3403
|
+
owner: grantee.owner,
|
|
3404
|
+
granteeAddress: grantee.address,
|
|
3405
|
+
publicKey: grantee.publicKey,
|
|
3406
|
+
permissionIds: grantee.permissionIds.map((id) => BigInt(id))
|
|
3407
|
+
};
|
|
3190
3408
|
} catch (error) {
|
|
3191
3409
|
throw new import_errors.BlockchainError(
|
|
3192
3410
|
`Failed to get grantee info by address: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
@@ -3250,6 +3468,117 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3250
3468
|
);
|
|
3251
3469
|
}
|
|
3252
3470
|
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Retrieves permission IDs for a specific grantee with flexible pagination.
|
|
3473
|
+
*
|
|
3474
|
+
* @remarks
|
|
3475
|
+
* **Pagination Behavior:**
|
|
3476
|
+
* Returns different types based on parameters:
|
|
3477
|
+
* - Without offset/limit: Returns `bigint[]` of all permissions using batched multicall
|
|
3478
|
+
* - With offset/limit: Returns paginated object with `permissionIds`, `totalCount`, and `hasMore`
|
|
3479
|
+
*
|
|
3480
|
+
* Uses gas-aware multicall for efficient batch fetching when retrieving all permissions.
|
|
3481
|
+
*
|
|
3482
|
+
* @param granteeId - Grantee ID to get permissions for
|
|
3483
|
+
* @param options - Optional pagination parameters
|
|
3484
|
+
* @param options.offset - Zero-based starting index for pagination. Defaults to 0 when fetching all permissions. Required for single-page requests.
|
|
3485
|
+
* @param options.limit - Maximum number of permission IDs to return per page. Defaults to 100 when fetching all permissions. Required for single-page requests.
|
|
3486
|
+
* @returns When called without options: Array of all permission IDs as `bigint[]`.
|
|
3487
|
+
* When called with offset and limit: Paginated result object containing `permissionIds` array,
|
|
3488
|
+
* `totalCount`, and `hasMore` boolean.
|
|
3489
|
+
* @throws {BlockchainError} When contract read operation fails
|
|
3490
|
+
*
|
|
3491
|
+
* @example
|
|
3492
|
+
* ```typescript
|
|
3493
|
+
* // Fetch all permissions (no pagination params)
|
|
3494
|
+
* const allPermissions = await vana.permissions.getGranteePermissionsPaginated(BigInt(1));
|
|
3495
|
+
* console.log(`Total permissions: ${allPermissions.length}`);
|
|
3496
|
+
*
|
|
3497
|
+
* // Fetch a specific page (with pagination params)
|
|
3498
|
+
* const page = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
|
|
3499
|
+
* offset: BigInt(0),
|
|
3500
|
+
* limit: BigInt(100)
|
|
3501
|
+
* });
|
|
3502
|
+
* console.log(`Fetched ${page.permissionIds.length} permissions`);
|
|
3503
|
+
* console.log(`Total: ${page.totalCount}, Has more: ${page.hasMore}`);
|
|
3504
|
+
*
|
|
3505
|
+
* // Fetch next page
|
|
3506
|
+
* if (page.hasMore) {
|
|
3507
|
+
* const nextPage = await vana.permissions.getGranteePermissionsPaginated(BigInt(1), {
|
|
3508
|
+
* offset: BigInt(100),
|
|
3509
|
+
* limit: BigInt(100)
|
|
3510
|
+
* });
|
|
3511
|
+
* }
|
|
3512
|
+
* ```
|
|
3513
|
+
*/
|
|
3514
|
+
async getGranteePermissionsPaginated(granteeId, options) {
|
|
3515
|
+
try {
|
|
3516
|
+
const chainId = await this.context.publicClient.getChainId();
|
|
3517
|
+
const DataPortabilityGranteesAddress = (0, import_addresses.getContractAddress)(
|
|
3518
|
+
chainId,
|
|
3519
|
+
"DataPortabilityGrantees"
|
|
3520
|
+
);
|
|
3521
|
+
const DataPortabilityGranteesAbi = (0, import_abi.getAbi)("DataPortabilityGrantees");
|
|
3522
|
+
const fetchOnlyOnePage = options?.offset !== void 0 && options?.limit !== void 0;
|
|
3523
|
+
if (fetchOnlyOnePage) {
|
|
3524
|
+
const result = await this.context.publicClient.readContract({
|
|
3525
|
+
address: DataPortabilityGranteesAddress,
|
|
3526
|
+
abi: DataPortabilityGranteesAbi,
|
|
3527
|
+
functionName: "granteePermissionsPaginated",
|
|
3528
|
+
args: [granteeId, options.offset, options.limit]
|
|
3529
|
+
});
|
|
3530
|
+
const [permissionIds, totalCount2, hasMore] = result;
|
|
3531
|
+
return {
|
|
3532
|
+
permissionIds: [...permissionIds],
|
|
3533
|
+
totalCount: totalCount2,
|
|
3534
|
+
hasMore
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
const countResult = await this.context.publicClient.readContract({
|
|
3538
|
+
address: DataPortabilityGranteesAddress,
|
|
3539
|
+
abi: DataPortabilityGranteesAbi,
|
|
3540
|
+
functionName: "granteePermissionsPaginated",
|
|
3541
|
+
args: [granteeId, BigInt(0), BigInt(1)]
|
|
3542
|
+
});
|
|
3543
|
+
const [, totalCount] = countResult;
|
|
3544
|
+
if (totalCount === BigInt(0)) {
|
|
3545
|
+
return [];
|
|
3546
|
+
}
|
|
3547
|
+
const batchSize = options?.limit ?? BigInt(100);
|
|
3548
|
+
const startOffset = options?.offset ?? BigInt(0);
|
|
3549
|
+
const endOffset = totalCount;
|
|
3550
|
+
const numBatches = Math.ceil(
|
|
3551
|
+
Number(endOffset - startOffset) / Number(batchSize)
|
|
3552
|
+
);
|
|
3553
|
+
const paginationCalls = Array.from({ length: numBatches }, (_, i) => ({
|
|
3554
|
+
address: DataPortabilityGranteesAddress,
|
|
3555
|
+
abi: DataPortabilityGranteesAbi,
|
|
3556
|
+
functionName: "granteePermissionsPaginated",
|
|
3557
|
+
args: [
|
|
3558
|
+
granteeId,
|
|
3559
|
+
startOffset + BigInt(i) * batchSize,
|
|
3560
|
+
batchSize
|
|
3561
|
+
]
|
|
3562
|
+
}));
|
|
3563
|
+
const results = await (0, import_multicall.gasAwareMulticall)(
|
|
3564
|
+
this.context.publicClient,
|
|
3565
|
+
{
|
|
3566
|
+
contracts: paginationCalls
|
|
3567
|
+
}
|
|
3568
|
+
);
|
|
3569
|
+
const allPermissionIds = [];
|
|
3570
|
+
for (const result of results) {
|
|
3571
|
+
const [permissionIds] = result;
|
|
3572
|
+
allPermissionIds.push(...permissionIds);
|
|
3573
|
+
}
|
|
3574
|
+
return allPermissionIds;
|
|
3575
|
+
} catch (error) {
|
|
3576
|
+
throw new import_errors.BlockchainError(
|
|
3577
|
+
`Failed to get grantee permissions: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
3578
|
+
error
|
|
3579
|
+
);
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3253
3582
|
// ===== DataPortabilityServersImplementation Methods =====
|
|
3254
3583
|
/**
|
|
3255
3584
|
* Get all server IDs for a user
|
|
@@ -3684,7 +4013,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3684
4013
|
if (response.type === "error") {
|
|
3685
4014
|
throw new import_errors.RelayerError(response.error);
|
|
3686
4015
|
}
|
|
3687
|
-
if (response.type === "
|
|
4016
|
+
if (response.type === "submitted") {
|
|
4017
|
+
hash = response.hash;
|
|
4018
|
+
} else if (response.type === "signed") {
|
|
3688
4019
|
hash = response.hash;
|
|
3689
4020
|
} else {
|
|
3690
4021
|
throw new Error("Unexpected response type from relayer");
|
|
@@ -3862,7 +4193,9 @@ class PermissionsController extends import_base.BaseController {
|
|
|
3862
4193
|
if (response.type === "error") {
|
|
3863
4194
|
throw new import_errors.RelayerError(response.error);
|
|
3864
4195
|
}
|
|
3865
|
-
if (response.type === "
|
|
4196
|
+
if (response.type === "submitted") {
|
|
4197
|
+
hash = response.hash;
|
|
4198
|
+
} else if (response.type === "signed") {
|
|
3866
4199
|
hash = response.hash;
|
|
3867
4200
|
} else {
|
|
3868
4201
|
throw new Error("Unexpected response type from relayer");
|