Skip to content

Commit b95e60a

Browse files
feat: add name, accessPrice, remainingAccess and isUserStrict properties to Contact (#221)
* feat: add name, accessPrice, remainingAccess and isUserStrict properties to Contact fix: stop exporting internal types
1 parent b4633fb commit b95e60a

File tree

8 files changed

+121
-53
lines changed

8 files changed

+121
-53
lines changed

src/utils/subgraphQuery.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { GraphQLClient, gql } from 'graphql-request';
2-
import { Contact, GraphQLResponse, ProtectedDataQuery } from '../index.js';
2+
import { Contact } from '../index.js';
33
import { WorkflowError } from './errors.js';
4+
import {
5+
GraphQLResponse,
6+
ProtectedDataQuery,
7+
} from '../web3mail/internalTypes.js';
48

59
const checkProtectedDataQuery = gql`
610
query GetValidContacts(
@@ -21,13 +25,14 @@ const checkProtectedDataQuery = gql`
2125
orderDirection: desc
2226
) {
2327
id
28+
name
2429
}
2530
}
2631
`;
2732

2833
export const getValidContact = async (
2934
graphQLClient: GraphQLClient,
30-
contacts: Contact[]
35+
contacts: Omit<Contact, 'name'>[]
3136
): Promise<Contact[]> => {
3237
if (contacts.length === 0) {
3338
return [];
@@ -66,13 +71,17 @@ export const getValidContact = async (
6671
);
6772

6873
// Convert protectedData[] into Contact[] using the map for constant time lookups
69-
return protectedDataList.map(({ id }) => {
74+
return protectedDataList.map(({ id, name }) => {
7075
const contact = contactsMap.get(id);
7176
if (contact) {
7277
return {
7378
address: id,
79+
name: name,
80+
remainingAccess: contact.remainingAccess,
81+
accessPrice: contact.accessPrice,
7482
owner: contact.owner,
7583
accessGrantTimestamp: contact.accessGrantTimestamp,
84+
isUserStrict: contact.isUserStrict,
7685
};
7786
}
7887
});

src/web3mail/fetchMyContacts.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { booleanSchema, throwIfMissing } from '../utils/validators.js';
22
import { fetchUserContacts } from './fetchUserContacts.js';
33
import {
4-
Contact,
54
DappAddressConsumer,
65
DappWhitelistAddressConsumer,
7-
FetchMyContactsParams,
86
IExecConsumer,
97
SubgraphConsumer,
10-
} from './types.js';
8+
} from './internalTypes.js';
9+
import { Contact, FetchMyContactsParams } from './types.js';
1110

1211
export type FetchMyContacts = typeof fetchMyContacts;
1312

src/web3mail/fetchUserContacts.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { PublishedDatasetorder } from 'iexec/IExecOrderbookModule';
2+
import { ZeroAddress } from 'ethers';
3+
import { IExec } from 'iexec';
14
import { ANY_DATASET_ADDRESS } from '../config/config.js';
25
import { handleIfProtocolError, WorkflowError } from '../utils/errors.js';
36
import { autoPaginateRequest } from '../utils/paginate.js';
@@ -9,14 +12,13 @@ import {
912
isEnsTest,
1013
throwIfMissing,
1114
} from '../utils/validators.js';
15+
import { Contact, FetchUserContactsParams } from './types.js';
1216
import {
13-
Contact,
1417
DappAddressConsumer,
1518
DappWhitelistAddressConsumer,
16-
FetchUserContactsParams,
1719
IExecConsumer,
1820
SubgraphConsumer,
19-
} from './types.js';
21+
} from './internalTypes.js';
2022

2123
export const fetchUserContacts = async ({
2224
graphQLClient = throwIfMissing(),
@@ -63,7 +65,7 @@ export const fetchUserContacts = async ({
6365
]);
6466

6567
const orders = dappOrders.concat(whitelistOrders);
66-
const myContacts: Contact[] = [];
68+
const myContacts: Omit<Contact, 'name'>[] = [];
6769
let web3DappResolvedAddress = vDappAddressOrENS;
6870
if (isEnsTest(vDappAddressOrENS)) {
6971
web3DappResolvedAddress = await iexec.ens.resolveName(vDappAddressOrENS);
@@ -78,7 +80,10 @@ export const fetchUserContacts = async ({
7880
const contact = {
7981
address: order.order.dataset.toLowerCase(),
8082
owner: order.signer.toLowerCase(),
83+
remainingAccess: order.remaining,
84+
accessPrice: order.order.datasetprice,
8185
accessGrantTimestamp: order.publicationTimestamp,
86+
isUserStrict: order.order.requesterrestrict !== ZeroAddress,
8287
};
8388
myContacts.push(contact);
8489
}
@@ -102,7 +107,12 @@ async function fetchAllOrdersByApp({
102107
userAddress,
103108
appAddress,
104109
isUserStrict,
105-
}) {
110+
}: {
111+
iexec: IExec;
112+
userAddress: string;
113+
appAddress: string;
114+
isUserStrict: boolean;
115+
}): Promise<PublishedDatasetorder[]> {
106116
const ordersFirstPage = iexec.orderbook.fetchDatasetOrderbook(
107117
ANY_DATASET_ADDRESS,
108118
{

src/web3mail/internalTypes.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { IExec } from 'iexec';
2+
import { AddressOrENS } from './types.js';
3+
import { GraphQLClient } from 'graphql-request';
4+
5+
export type ProtectedDataQuery = {
6+
id: string;
7+
name: string;
8+
};
9+
10+
export type GraphQLResponse = {
11+
protectedDatas: ProtectedDataQuery[];
12+
};
13+
14+
export type DappAddressConsumer = {
15+
dappAddressOrENS: AddressOrENS;
16+
};
17+
18+
export type IpfsNodeConfigConsumer = {
19+
ipfsNode: string;
20+
};
21+
22+
export type IpfsGatewayConfigConsumer = {
23+
ipfsGateway: string;
24+
};
25+
26+
export type DappWhitelistAddressConsumer = {
27+
dappWhitelistAddress: string;
28+
};
29+
30+
export type IExecConsumer = {
31+
iexec: IExec;
32+
};
33+
34+
export type SubgraphConsumer = {
35+
graphQLClient: GraphQLClient;
36+
};

src/web3mail/sendEmail.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,15 @@ import {
2626
checkUserVoucher,
2727
filterWorkerpoolOrders,
2828
} from './sendEmail.models.js';
29+
import { SendEmailParams, SendEmailResponse } from './types.js';
2930
import {
3031
DappAddressConsumer,
3132
DappWhitelistAddressConsumer,
3233
IExecConsumer,
3334
IpfsGatewayConfigConsumer,
3435
IpfsNodeConfigConsumer,
35-
SendEmailParams,
36-
SendEmailResponse,
3736
SubgraphConsumer,
38-
} from './types.js';
37+
} from './internalTypes.js';
3938

4039
export type SendEmail = typeof sendEmail;
4140

src/web3mail/types.ts

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import { GraphQLClient } from 'graphql-request';
2-
import { EnhancedWallet, IExec } from 'iexec';
1+
import { EnhancedWallet } from 'iexec';
32
import { IExecConfigOptions } from 'iexec/IExecConfig';
43

54
export type Web3SignerProvider = EnhancedWallet;
65

7-
export type IExecConsumer = {
8-
iexec: IExec;
9-
};
10-
116
export type ENS = string;
127

138
export type AddressOrENS = Address | ENS;
@@ -20,6 +15,10 @@ export type Contact = {
2015
address: Address;
2116
owner: Address;
2217
accessGrantTimestamp: TimeStamp;
18+
isUserStrict: boolean;
19+
name: string;
20+
remainingAccess: number;
21+
accessPrice: number;
2322
};
2423

2524
export type SendEmailParams = {
@@ -54,21 +53,6 @@ export type SendEmailResponse = {
5453
taskId: string;
5554
};
5655

57-
/**
58-
* Internal props for querying the subgraph
59-
*/
60-
export type ProtectedDataQuery = {
61-
id: string;
62-
};
63-
64-
export type GraphQLResponse = {
65-
protectedDatas: ProtectedDataQuery[];
66-
};
67-
68-
export type SubgraphConsumer = {
69-
graphQLClient: GraphQLClient;
70-
};
71-
7256
/**
7357
* Configuration options for Web3Mail.
7458
*/
@@ -116,19 +100,3 @@ export type Web3MailConfigOptions = {
116100
*/
117101
allowExperimentalNetworks?: boolean;
118102
};
119-
120-
export type DappAddressConsumer = {
121-
dappAddressOrENS: AddressOrENS;
122-
};
123-
124-
export type IpfsNodeConfigConsumer = {
125-
ipfsNode: string;
126-
};
127-
128-
export type IpfsGatewayConfigConsumer = {
129-
ipfsGateway: string;
130-
};
131-
132-
export type DappWhitelistAddressConsumer = {
133-
dappWhitelistAddress: string;
134-
};

tests/e2e/fetchUserContacts.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,33 @@ describe('web3mail.fetchMyContacts()', () => {
4343
}, 4 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME);
4444

4545
describe('when no access is granted', () => {
46+
it('contacts should contain name, accessPrice, remainingAccess, owner, accessGrantTimestamp, and isUserStrict', async () => {
47+
const userWithAccess = Wallet.createRandom().address;
48+
49+
await web3mail.init();
50+
// eslint-disable-next-line @typescript-eslint/dot-notation
51+
const authorizedApp = web3mail['dappAddressOrENS'];
52+
53+
await dataProtector.grantAccess({
54+
authorizedApp: authorizedApp,
55+
protectedData: protectedData1.address,
56+
authorizedUser: userWithAccess,
57+
});
58+
59+
const contacts = await web3mail.fetchUserContacts({
60+
userAddress: userWithAccess,
61+
isUserStrict: true,
62+
});
63+
expect(contacts.length).toBe(1);
64+
expect(contacts[0].address).toBe(protectedData1.address.toLowerCase());
65+
expect(contacts[0].owner).toBeDefined();
66+
expect(contacts[0].accessPrice).toBe(0);
67+
expect(contacts[0].remainingAccess).toBe(1);
68+
expect(contacts[0].accessGrantTimestamp).toBeDefined();
69+
expect(contacts[0].isUserStrict).toBe(true);
70+
expect(contacts[0].name).toBe('test do not use');
71+
});
72+
4673
it(
4774
'should return an empty contact array',
4875
async () => {

tests/unit/utils/subgraphQuery.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { Contact } from '../../../src/web3mail/types.js';
88

99
describe('getValidContact', () => {
1010
// Define the variables in the outermost scope
11-
let contacts: Contact[];
11+
let contacts: Omit<Contact, 'name'>[];
1212
let graphQLClient: GraphQLClient;
1313

1414
beforeAll(() => {
@@ -18,16 +18,25 @@ describe('getValidContact', () => {
1818
address: 'address1',
1919
owner: 'owner1',
2020
accessGrantTimestamp: '2023-06-08T09:32:29.761Z',
21+
remainingAccess: 1,
22+
accessPrice: 0,
23+
isUserStrict: true,
2124
},
2225
{
2326
address: 'address2',
2427
owner: 'owner2',
2528
accessGrantTimestamp: '2023-06-09T14:21:17.231Z',
29+
remainingAccess: 1,
30+
accessPrice: 0,
31+
isUserStrict: true,
2632
},
2733
{
2834
address: 'address3',
2935
owner: 'owner3',
3036
accessGrantTimestamp: '2023-06-10T14:21:17.231Z',
37+
remainingAccess: 1,
38+
accessPrice: 0,
39+
isUserStrict: true,
3140
},
3241
];
3342

@@ -38,7 +47,10 @@ describe('getValidContact', () => {
3847
it('should fetch valid contacts', async () => {
3948
// Mock the request method of the GraphQLClient instance
4049
jest.spyOn(graphQLClient, 'request').mockResolvedValue({
41-
protectedDatas: [{ id: 'address1' }, { id: 'address3' }],
50+
protectedDatas: [
51+
{ id: 'address1', name: 'Contact 1' },
52+
{ id: 'address3', name: 'Contact 3' },
53+
],
4254
});
4355

4456
const validContacts = await getValidContact(graphQLClient, contacts);
@@ -48,11 +60,19 @@ describe('getValidContact', () => {
4860
address: 'address1',
4961
owner: 'owner1',
5062
accessGrantTimestamp: '2023-06-08T09:32:29.761Z',
63+
name: 'Contact 1',
64+
remainingAccess: 1,
65+
accessPrice: 0,
66+
isUserStrict: true,
5167
},
5268
{
5369
address: 'address3',
5470
owner: 'owner3',
5571
accessGrantTimestamp: '2023-06-10T14:21:17.231Z',
72+
name: 'Contact 3',
73+
remainingAccess: 1,
74+
accessPrice: 0,
75+
isUserStrict: true,
5676
},
5777
]);
5878

0 commit comments

Comments
 (0)