@iexec/web3mail 1.9.0 → 2.0.0
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/README.md +7 -7
- package/dist/config/config.d.ts +6 -1
- package/dist/config/config.js +21 -10
- package/dist/config/config.js.map +1 -1
- package/dist/utils/getChainId.js +7 -2
- package/dist/utils/getChainId.js.map +1 -1
- package/dist/utils/getWeb3Provider.d.ts +10 -2
- package/dist/utils/getWeb3Provider.js +12 -7
- package/dist/utils/getWeb3Provider.js.map +1 -1
- package/dist/utils/resolveDappAddressFromCompass.d.ts +2 -2
- package/dist/utils/validators.d.ts +0 -2
- package/dist/utils/validators.js +0 -4
- package/dist/utils/validators.js.map +1 -1
- package/dist/web3mail/IExecWeb3mail.d.ts +2 -2
- package/dist/web3mail/IExecWeb3mail.js +13 -14
- package/dist/web3mail/IExecWeb3mail.js.map +1 -1
- package/dist/web3mail/fetchMyContacts.d.ts +1 -1
- package/dist/web3mail/fetchMyContacts.js +2 -2
- package/dist/web3mail/fetchMyContacts.js.map +1 -1
- package/dist/web3mail/fetchUserContacts.d.ts +1 -1
- package/dist/web3mail/fetchUserContacts.js +20 -25
- package/dist/web3mail/fetchUserContacts.js.map +1 -1
- package/dist/web3mail/internalTypes.d.ts +2 -2
- package/dist/web3mail/prepareEmailCampaign.d.ts +1 -1
- package/dist/web3mail/prepareEmailCampaign.js +10 -10
- package/dist/web3mail/prepareEmailCampaign.js.map +1 -1
- package/dist/web3mail/sendEmail.d.ts +1 -1
- package/dist/web3mail/sendEmail.js +21 -41
- package/dist/web3mail/sendEmail.js.map +1 -1
- package/dist/web3mail/sendEmail.models.d.ts +8 -27
- package/dist/web3mail/sendEmail.models.js +5 -28
- package/dist/web3mail/sendEmail.models.js.map +1 -1
- package/dist/web3mail/sendEmailCampaign.d.ts +1 -1
- package/dist/web3mail/sendEmailCampaign.js +8 -9
- package/dist/web3mail/sendEmailCampaign.js.map +1 -1
- package/dist/web3mail/types.d.ts +8 -11
- package/package.json +4 -4
- package/src/config/config.ts +24 -12
- package/src/utils/getChainId.ts +11 -2
- package/src/utils/getWeb3Provider.ts +13 -6
- package/src/utils/resolveDappAddressFromCompass.ts +2 -2
- package/src/utils/validators.ts +0 -11
- package/src/web3mail/IExecWeb3mail.ts +20 -23
- package/src/web3mail/fetchMyContacts.ts +2 -2
- package/src/web3mail/fetchUserContacts.ts +21 -27
- package/src/web3mail/internalTypes.ts +2 -2
- package/src/web3mail/prepareEmailCampaign.ts +11 -11
- package/src/web3mail/sendEmail.models.ts +6 -68
- package/src/web3mail/sendEmail.ts +26 -58
- package/src/web3mail/sendEmailCampaign.ts +10 -11
- package/src/web3mail/types.ts +8 -13
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
Contact,
|
|
12
12
|
FetchUserContactsParams,
|
|
13
13
|
SendEmailParams,
|
|
14
|
-
|
|
14
|
+
Address,
|
|
15
15
|
Web3MailConfigOptions,
|
|
16
16
|
SendEmailResponse,
|
|
17
17
|
Web3SignerProvider,
|
|
@@ -34,8 +34,8 @@ type EthersCompatibleProvider =
|
|
|
34
34
|
| string;
|
|
35
35
|
|
|
36
36
|
interface Web3mailResolvedConfig {
|
|
37
|
-
|
|
38
|
-
dappWhitelistAddress:
|
|
37
|
+
dappAddress: Address;
|
|
38
|
+
dappWhitelistAddress: Address;
|
|
39
39
|
graphQLClient: GraphQLClient;
|
|
40
40
|
ipfsNode: string;
|
|
41
41
|
ipfsGateway: string;
|
|
@@ -45,9 +45,9 @@ interface Web3mailResolvedConfig {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export class IExecWeb3mail {
|
|
48
|
-
private
|
|
48
|
+
private dappAddress!: Address;
|
|
49
49
|
|
|
50
|
-
private dappWhitelistAddress!:
|
|
50
|
+
private dappWhitelistAddress!: Address;
|
|
51
51
|
|
|
52
52
|
private graphQLClient!: GraphQLClient;
|
|
53
53
|
|
|
@@ -68,17 +68,17 @@ export class IExecWeb3mail {
|
|
|
68
68
|
private options: Web3MailConfigOptions;
|
|
69
69
|
|
|
70
70
|
constructor(
|
|
71
|
-
ethProvider
|
|
71
|
+
ethProvider: EthersCompatibleProvider,
|
|
72
72
|
options?: Web3MailConfigOptions
|
|
73
73
|
) {
|
|
74
|
-
this.ethProvider = ethProvider
|
|
74
|
+
this.ethProvider = ethProvider;
|
|
75
75
|
this.options = options || {};
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
async init(): Promise<void> {
|
|
79
79
|
if (!this.initPromise) {
|
|
80
80
|
this.initPromise = this.resolveConfig().then((config) => {
|
|
81
|
-
this.
|
|
81
|
+
this.dappAddress = config.dappAddress;
|
|
82
82
|
this.dappWhitelistAddress = config.dappWhitelistAddress;
|
|
83
83
|
this.graphQLClient = config.graphQLClient;
|
|
84
84
|
this.ipfsNode = config.ipfsNode;
|
|
@@ -99,7 +99,7 @@ export class IExecWeb3mail {
|
|
|
99
99
|
...args,
|
|
100
100
|
iexec: this.iexec,
|
|
101
101
|
graphQLClient: this.graphQLClient,
|
|
102
|
-
|
|
102
|
+
dappAddress: this.dappAddress,
|
|
103
103
|
dappWhitelistAddress: this.dappWhitelistAddress,
|
|
104
104
|
});
|
|
105
105
|
}
|
|
@@ -111,7 +111,7 @@ export class IExecWeb3mail {
|
|
|
111
111
|
...args,
|
|
112
112
|
iexec: this.iexec,
|
|
113
113
|
graphQLClient: this.graphQLClient,
|
|
114
|
-
|
|
114
|
+
dappAddress: this.dappAddress,
|
|
115
115
|
dappWhitelistAddress: this.dappWhitelistAddress,
|
|
116
116
|
});
|
|
117
117
|
}
|
|
@@ -121,12 +121,11 @@ export class IExecWeb3mail {
|
|
|
121
121
|
await isValidProvider(this.iexec);
|
|
122
122
|
return sendEmail({
|
|
123
123
|
...args,
|
|
124
|
-
|
|
125
|
-
args.workerpoolAddressOrEns || this.defaultWorkerpool,
|
|
124
|
+
workerpoolAddress: args.workerpoolAddress || this.defaultWorkerpool,
|
|
126
125
|
iexec: this.iexec,
|
|
127
126
|
ipfsNode: this.ipfsNode,
|
|
128
127
|
ipfsGateway: this.ipfsGateway,
|
|
129
|
-
|
|
128
|
+
dappAddress: this.dappAddress,
|
|
130
129
|
dappWhitelistAddress: this.dappWhitelistAddress,
|
|
131
130
|
graphQLClient: this.graphQLClient,
|
|
132
131
|
});
|
|
@@ -136,16 +135,15 @@ export class IExecWeb3mail {
|
|
|
136
135
|
args: PrepareEmailCampaignParams
|
|
137
136
|
): Promise<PrepareEmailCampaignResponse> {
|
|
138
137
|
await this.init();
|
|
139
|
-
|
|
138
|
+
|
|
140
139
|
return prepareEmailCampaign({
|
|
141
140
|
...args,
|
|
142
|
-
|
|
143
|
-
args.workerpoolAddressOrEns || this.defaultWorkerpool,
|
|
141
|
+
workerpoolAddress: args.workerpoolAddress || this.defaultWorkerpool,
|
|
144
142
|
iexec: this.iexec,
|
|
145
143
|
dataProtector: this.dataProtector,
|
|
146
144
|
ipfsNode: this.ipfsNode,
|
|
147
145
|
ipfsGateway: this.ipfsGateway,
|
|
148
|
-
|
|
146
|
+
dappAddress: this.dappAddress,
|
|
149
147
|
});
|
|
150
148
|
}
|
|
151
149
|
|
|
@@ -156,8 +154,7 @@ export class IExecWeb3mail {
|
|
|
156
154
|
await isValidProvider(this.iexec);
|
|
157
155
|
return sendEmailCampaign({
|
|
158
156
|
...args,
|
|
159
|
-
|
|
160
|
-
args.workerpoolAddressOrEns || this.defaultWorkerpool,
|
|
157
|
+
workerpoolAddress: args.workerpoolAddress || this.defaultWorkerpool,
|
|
161
158
|
dataProtector: this.dataProtector,
|
|
162
159
|
});
|
|
163
160
|
}
|
|
@@ -189,8 +186,8 @@ export class IExecWeb3mail {
|
|
|
189
186
|
const subgraphUrl =
|
|
190
187
|
this.options?.dataProtectorSubgraph ||
|
|
191
188
|
chainDefaultConfig?.dataProtectorSubgraph;
|
|
192
|
-
const
|
|
193
|
-
this.options?.
|
|
189
|
+
const dappAddress =
|
|
190
|
+
this.options?.dappAddress ||
|
|
194
191
|
chainDefaultConfig?.dappAddress ||
|
|
195
192
|
(await resolveDappAddressFromCompass(
|
|
196
193
|
await iexec.config.resolveCompassURL(),
|
|
@@ -205,7 +202,7 @@ export class IExecWeb3mail {
|
|
|
205
202
|
|
|
206
203
|
const missing = [];
|
|
207
204
|
if (!subgraphUrl) missing.push('dataProtectorSubgraph');
|
|
208
|
-
if (!
|
|
205
|
+
if (!dappAddress) missing.push('dappAddress');
|
|
209
206
|
if (!dappWhitelistAddress) missing.push('whitelistSmartContract');
|
|
210
207
|
if (!ipfsGateway) missing.push('ipfsGateway');
|
|
211
208
|
if (!defaultWorkerpool) missing.push('prodWorkerpoolAddress');
|
|
@@ -237,7 +234,7 @@ export class IExecWeb3mail {
|
|
|
237
234
|
});
|
|
238
235
|
|
|
239
236
|
return {
|
|
240
|
-
|
|
237
|
+
dappAddress,
|
|
241
238
|
dappWhitelistAddress: dappWhitelistAddress.toLowerCase(),
|
|
242
239
|
defaultWorkerpool,
|
|
243
240
|
graphQLClient,
|
|
@@ -13,7 +13,7 @@ export type FetchMyContacts = typeof fetchMyContacts;
|
|
|
13
13
|
export const fetchMyContacts = async ({
|
|
14
14
|
graphQLClient = throwIfMissing(),
|
|
15
15
|
iexec = throwIfMissing(),
|
|
16
|
-
|
|
16
|
+
dappAddress = throwIfMissing(),
|
|
17
17
|
dappWhitelistAddress = throwIfMissing(),
|
|
18
18
|
isUserStrict = false,
|
|
19
19
|
bulkOnly = false,
|
|
@@ -31,7 +31,7 @@ export const fetchMyContacts = async ({
|
|
|
31
31
|
return fetchUserContacts({
|
|
32
32
|
iexec,
|
|
33
33
|
graphQLClient,
|
|
34
|
-
|
|
34
|
+
dappAddress,
|
|
35
35
|
dappWhitelistAddress,
|
|
36
36
|
userAddress,
|
|
37
37
|
isUserStrict: vIsUserStrict,
|
|
@@ -6,10 +6,8 @@ import { handleIfProtocolError, WorkflowError } from '../utils/errors.js';
|
|
|
6
6
|
import { autoPaginateRequest } from '../utils/paginate.js';
|
|
7
7
|
import { getValidContact } from '../utils/subgraphQuery.js';
|
|
8
8
|
import {
|
|
9
|
-
addressOrEnsSchema,
|
|
10
9
|
addressSchema,
|
|
11
10
|
booleanSchema,
|
|
12
|
-
isEnsTest,
|
|
13
11
|
throwIfMissing,
|
|
14
12
|
} from '../utils/validators.js';
|
|
15
13
|
import { Contact, FetchUserContactsParams } from './types.js';
|
|
@@ -23,7 +21,7 @@ import {
|
|
|
23
21
|
export const fetchUserContacts = async ({
|
|
24
22
|
graphQLClient = throwIfMissing(),
|
|
25
23
|
iexec = throwIfMissing(),
|
|
26
|
-
|
|
24
|
+
dappAddress = throwIfMissing(),
|
|
27
25
|
dappWhitelistAddress = throwIfMissing(),
|
|
28
26
|
userAddress,
|
|
29
27
|
isUserStrict = false,
|
|
@@ -33,29 +31,29 @@ export const fetchUserContacts = async ({
|
|
|
33
31
|
DappAddressConsumer &
|
|
34
32
|
DappWhitelistAddressConsumer &
|
|
35
33
|
FetchUserContactsParams): Promise<Contact[]> => {
|
|
36
|
-
const vDappAddressOrENS = addressOrEnsSchema()
|
|
37
|
-
.required()
|
|
38
|
-
.label('dappAddressOrENS')
|
|
39
|
-
.validateSync(dappAddressOrENS);
|
|
40
|
-
const vDappWhitelistAddress = addressSchema()
|
|
41
|
-
.required()
|
|
42
|
-
.label('dappWhitelistAddress')
|
|
43
|
-
.validateSync(dappWhitelistAddress);
|
|
44
|
-
const vUserAddress = addressOrEnsSchema()
|
|
45
|
-
.required()
|
|
46
|
-
.label('userAddress')
|
|
47
|
-
.validateSync(userAddress);
|
|
48
|
-
const vIsUserStrict = booleanSchema()
|
|
49
|
-
.label('isUserStrict')
|
|
50
|
-
.validateSync(isUserStrict);
|
|
51
|
-
const vBulkOnly = booleanSchema().label('bulkOnly').validateSync(bulkOnly);
|
|
52
|
-
|
|
53
34
|
try {
|
|
35
|
+
const address = addressSchema()
|
|
36
|
+
.required()
|
|
37
|
+
.label('dappAddress')
|
|
38
|
+
.validateSync(dappAddress);
|
|
39
|
+
const vDappWhitelistAddress = addressSchema()
|
|
40
|
+
.required()
|
|
41
|
+
.label('dappWhitelistAddress')
|
|
42
|
+
.validateSync(dappWhitelistAddress);
|
|
43
|
+
const vUserAddress = addressSchema()
|
|
44
|
+
.required()
|
|
45
|
+
.label('userAddress')
|
|
46
|
+
.validateSync(userAddress);
|
|
47
|
+
const vIsUserStrict = booleanSchema()
|
|
48
|
+
.label('isUserStrict')
|
|
49
|
+
.validateSync(isUserStrict);
|
|
50
|
+
const vBulkOnly = booleanSchema().label('bulkOnly').validateSync(bulkOnly);
|
|
51
|
+
|
|
54
52
|
const [dappOrders, whitelistOrders] = await Promise.all([
|
|
55
53
|
fetchAllOrdersByApp({
|
|
56
54
|
iexec,
|
|
57
55
|
userAddress: vUserAddress,
|
|
58
|
-
appAddress:
|
|
56
|
+
appAddress: address,
|
|
59
57
|
isUserStrict: vIsUserStrict,
|
|
60
58
|
bulkOnly: vBulkOnly,
|
|
61
59
|
}),
|
|
@@ -70,14 +68,10 @@ export const fetchUserContacts = async ({
|
|
|
70
68
|
|
|
71
69
|
const orders = dappOrders.concat(whitelistOrders);
|
|
72
70
|
const myContacts: Omit<Contact, 'name'>[] = [];
|
|
73
|
-
|
|
74
|
-
if (isEnsTest(vDappAddressOrENS)) {
|
|
75
|
-
web3DappResolvedAddress = await iexec.ens.resolveName(vDappAddressOrENS);
|
|
76
|
-
}
|
|
71
|
+
|
|
77
72
|
orders.forEach((order) => {
|
|
78
73
|
if (
|
|
79
|
-
order.order.apprestrict.toLowerCase() ===
|
|
80
|
-
web3DappResolvedAddress.toLowerCase() ||
|
|
74
|
+
order.order.apprestrict.toLowerCase() === address.toLowerCase() ||
|
|
81
75
|
order.order.apprestrict.toLowerCase() ===
|
|
82
76
|
vDappWhitelistAddress.toLowerCase()
|
|
83
77
|
) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IExec } from 'iexec';
|
|
2
2
|
import { IExecDataProtectorCore } from '@iexec/dataprotector';
|
|
3
|
-
import {
|
|
3
|
+
import { Address } from './types.js';
|
|
4
4
|
import { GraphQLClient } from 'graphql-request';
|
|
5
5
|
|
|
6
6
|
export type ProtectedDataQuery = {
|
|
@@ -13,7 +13,7 @@ export type GraphQLResponse = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export type DappAddressConsumer = {
|
|
16
|
-
|
|
16
|
+
dappAddress: Address;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export type IpfsNodeConfigConsumer = {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { handleIfProtocolError, WorkflowError } from '../utils/errors.js';
|
|
8
8
|
import * as ipfs from '../utils/ipfs-service.js';
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
addressSchema,
|
|
11
11
|
contentTypeSchema,
|
|
12
12
|
emailContentSchema,
|
|
13
13
|
emailSubjectSchema,
|
|
@@ -33,8 +33,8 @@ export type PrepareEmailCampaign = typeof prepareEmailCampaign;
|
|
|
33
33
|
export const prepareEmailCampaign = async ({
|
|
34
34
|
iexec = throwIfMissing(),
|
|
35
35
|
dataProtector = throwIfMissing(),
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
workerpoolAddress,
|
|
37
|
+
dappAddress,
|
|
38
38
|
ipfsNode,
|
|
39
39
|
ipfsGateway,
|
|
40
40
|
senderName,
|
|
@@ -53,9 +53,9 @@ export const prepareEmailCampaign = async ({
|
|
|
53
53
|
DataProtectorConsumer &
|
|
54
54
|
PrepareEmailCampaignParams): Promise<PrepareEmailCampaignResponse> => {
|
|
55
55
|
try {
|
|
56
|
-
const
|
|
57
|
-
.label('
|
|
58
|
-
.validateSync(
|
|
56
|
+
const vWorkerpoolAddress = addressSchema()
|
|
57
|
+
.label('workerpoolAddress')
|
|
58
|
+
.validateSync(workerpoolAddress);
|
|
59
59
|
|
|
60
60
|
const vSenderName = senderNameSchema()
|
|
61
61
|
.label('senderName')
|
|
@@ -77,10 +77,10 @@ export const prepareEmailCampaign = async ({
|
|
|
77
77
|
|
|
78
78
|
const vLabel = labelSchema().label('label').validateSync(label);
|
|
79
79
|
|
|
80
|
-
const
|
|
80
|
+
const vDappAddress = addressSchema()
|
|
81
81
|
.required()
|
|
82
|
-
.label('
|
|
83
|
-
.validateSync(
|
|
82
|
+
.label('dappAddress')
|
|
83
|
+
.validateSync(dappAddress);
|
|
84
84
|
|
|
85
85
|
const vAppMaxPrice = positiveNumberSchema()
|
|
86
86
|
.label('appMaxPrice')
|
|
@@ -139,10 +139,10 @@ export const prepareEmailCampaign = async ({
|
|
|
139
139
|
// TODO: end factor this
|
|
140
140
|
const { bulkRequest: campaignRequest } =
|
|
141
141
|
await dataProtector.prepareBulkRequest({
|
|
142
|
-
app:
|
|
142
|
+
app: vDappAddress,
|
|
143
143
|
appMaxPrice: vAppMaxPrice,
|
|
144
144
|
workerpoolMaxPrice: vWorkerpoolMaxPrice,
|
|
145
|
-
workerpool:
|
|
145
|
+
workerpool: vWorkerpoolAddress,
|
|
146
146
|
args: vLabel,
|
|
147
147
|
inputFiles: [],
|
|
148
148
|
secrets,
|
|
@@ -1,88 +1,26 @@
|
|
|
1
|
-
import { Address, BN } from 'iexec';
|
|
2
1
|
import { PublishedWorkerpoolorder } from 'iexec/IExecOrderbookModule';
|
|
3
|
-
// import { VoucherInfo } from 'iexec/IExecVoucherModule';
|
|
4
|
-
|
|
5
|
-
// To import from 'iexec' once exported
|
|
6
|
-
type VoucherInfo = {
|
|
7
|
-
owner: Address;
|
|
8
|
-
address: Address;
|
|
9
|
-
type: BN;
|
|
10
|
-
balance: BN;
|
|
11
|
-
expirationTimestamp: BN;
|
|
12
|
-
sponsoredApps: Address[];
|
|
13
|
-
sponsoredDatasets: Address[];
|
|
14
|
-
sponsoredWorkerpools: Address[];
|
|
15
|
-
allowanceAmount: BN;
|
|
16
|
-
authorizedAccounts: Address[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function bnToNumber(bn: BN) {
|
|
20
|
-
return Number(bn.toString());
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function checkUserVoucher({
|
|
24
|
-
userVoucher,
|
|
25
|
-
}: {
|
|
26
|
-
userVoucher: VoucherInfo;
|
|
27
|
-
}) {
|
|
28
|
-
if (bnToNumber(userVoucher.expirationTimestamp) < Date.now() / 1000) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
'Oops, it seems your voucher has expired. You might want to ask for a top up. Check on https://builder.iex.ec/'
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (bnToNumber(userVoucher.balance) === 0) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
'Oops, it seems your voucher is empty. You might want to ask for a top up. Check on https://builder.iex.ec/'
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
2
|
|
|
41
3
|
export function filterWorkerpoolOrders({
|
|
42
4
|
workerpoolOrders,
|
|
43
5
|
workerpoolMaxPrice,
|
|
44
|
-
useVoucher,
|
|
45
|
-
userVoucher,
|
|
46
6
|
}: {
|
|
47
7
|
workerpoolOrders: PublishedWorkerpoolorder[];
|
|
48
8
|
workerpoolMaxPrice: number;
|
|
49
|
-
useVoucher: boolean;
|
|
50
|
-
userVoucher?: VoucherInfo;
|
|
51
9
|
}) {
|
|
52
10
|
if (workerpoolOrders.length === 0) {
|
|
53
11
|
return null;
|
|
54
12
|
}
|
|
55
13
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
throw new Error(
|
|
62
|
-
'useVoucher === true but userVoucher is undefined? Hum...'
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
// only voucher sponsored workerpoolorders
|
|
66
|
-
eligibleWorkerpoolOrders = eligibleWorkerpoolOrders.filter(({ order }) =>
|
|
67
|
-
userVoucher.sponsoredWorkerpools.includes(order.workerpool)
|
|
14
|
+
const [cheapestOrder] = workerpoolOrders
|
|
15
|
+
.slice()
|
|
16
|
+
.sort(
|
|
17
|
+
(order1, order2) =>
|
|
18
|
+
order1.order.workerpoolprice - order2.order.workerpoolprice
|
|
68
19
|
);
|
|
69
|
-
if (eligibleWorkerpoolOrders.length === 0) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
'Found some workerpool orders but none can be sponsored by your voucher.'
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
maxVoucherSponsoredAmount = bnToNumber(userVoucher.balance);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const [cheapestOrder] = eligibleWorkerpoolOrders.sort(
|
|
78
|
-
(order1, order2) =>
|
|
79
|
-
order1.order.workerpoolprice - order2.order.workerpoolprice
|
|
80
|
-
);
|
|
81
20
|
|
|
82
21
|
if (
|
|
83
22
|
!cheapestOrder ||
|
|
84
|
-
cheapestOrder.order.workerpoolprice >
|
|
85
|
-
workerpoolMaxPrice + maxVoucherSponsoredAmount
|
|
23
|
+
cheapestOrder.order.workerpoolprice > workerpoolMaxPrice
|
|
86
24
|
) {
|
|
87
25
|
return null;
|
|
88
26
|
}
|
|
@@ -11,9 +11,7 @@ import { generateSecureUniqueId } from '../utils/generateUniqueId.js';
|
|
|
11
11
|
import * as ipfs from '../utils/ipfs-service.js';
|
|
12
12
|
import { checkProtectedDataValidity } from '../utils/subgraphQuery.js';
|
|
13
13
|
import {
|
|
14
|
-
addressOrEnsSchema,
|
|
15
14
|
addressSchema,
|
|
16
|
-
booleanSchema,
|
|
17
15
|
contentTypeSchema,
|
|
18
16
|
emailContentSchema,
|
|
19
17
|
emailSubjectSchema,
|
|
@@ -22,10 +20,7 @@ import {
|
|
|
22
20
|
senderNameSchema,
|
|
23
21
|
throwIfMissing,
|
|
24
22
|
} from '../utils/validators.js';
|
|
25
|
-
import {
|
|
26
|
-
checkUserVoucher,
|
|
27
|
-
filterWorkerpoolOrders,
|
|
28
|
-
} from './sendEmail.models.js';
|
|
23
|
+
import { filterWorkerpoolOrders } from './sendEmail.models.js';
|
|
29
24
|
import { SendEmailParams, SendEmailResponse } from './types.js';
|
|
30
25
|
import {
|
|
31
26
|
DappAddressConsumer,
|
|
@@ -41,8 +36,8 @@ export type SendEmail = typeof sendEmail;
|
|
|
41
36
|
export const sendEmail = async ({
|
|
42
37
|
graphQLClient = throwIfMissing(),
|
|
43
38
|
iexec = throwIfMissing(),
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
workerpoolAddress,
|
|
40
|
+
dappAddress,
|
|
46
41
|
dappWhitelistAddress,
|
|
47
42
|
ipfsNode,
|
|
48
43
|
ipfsGateway,
|
|
@@ -55,7 +50,6 @@ export const sendEmail = async ({
|
|
|
55
50
|
workerpoolMaxPrice = MAX_DESIRED_WORKERPOOL_ORDER_PRICE,
|
|
56
51
|
senderName,
|
|
57
52
|
protectedData,
|
|
58
|
-
useVoucher = false,
|
|
59
53
|
}: IExecConsumer &
|
|
60
54
|
SubgraphConsumer &
|
|
61
55
|
DappAddressConsumer &
|
|
@@ -63,7 +57,7 @@ export const sendEmail = async ({
|
|
|
63
57
|
IpfsNodeConfigConsumer &
|
|
64
58
|
IpfsGatewayConfigConsumer &
|
|
65
59
|
SendEmailParams): Promise<SendEmailResponse> => {
|
|
66
|
-
const vDatasetAddress =
|
|
60
|
+
const vDatasetAddress = addressSchema()
|
|
67
61
|
.required()
|
|
68
62
|
.label('protectedData')
|
|
69
63
|
.validateSync(protectedData);
|
|
@@ -89,15 +83,15 @@ export const sendEmail = async ({
|
|
|
89
83
|
|
|
90
84
|
const vLabel = labelSchema().label('label').validateSync(label);
|
|
91
85
|
|
|
92
|
-
const
|
|
86
|
+
const vWorkerpoolAddress = addressSchema()
|
|
93
87
|
.required()
|
|
94
|
-
.label('
|
|
95
|
-
.validateSync(
|
|
88
|
+
.label('workerpoolAddress')
|
|
89
|
+
.validateSync(workerpoolAddress);
|
|
96
90
|
|
|
97
|
-
const
|
|
91
|
+
const vDappAddress = addressSchema()
|
|
98
92
|
.required()
|
|
99
|
-
.label('
|
|
100
|
-
.validateSync(
|
|
93
|
+
.label('dappAddress')
|
|
94
|
+
.validateSync(dappAddress);
|
|
101
95
|
|
|
102
96
|
const vDappWhitelistAddress = addressSchema()
|
|
103
97
|
.required()
|
|
@@ -116,10 +110,6 @@ export const sendEmail = async ({
|
|
|
116
110
|
.label('workerpoolMaxPrice')
|
|
117
111
|
.validateSync(workerpoolMaxPrice);
|
|
118
112
|
|
|
119
|
-
const vUseVoucher = booleanSchema()
|
|
120
|
-
.label('useVoucher')
|
|
121
|
-
.validateSync(useVoucher);
|
|
122
|
-
|
|
123
113
|
// Check protected data schema through subgraph
|
|
124
114
|
const isValidProtectedData = await checkProtectedDataValidity(
|
|
125
115
|
graphQLClient,
|
|
@@ -134,28 +124,13 @@ export const sendEmail = async ({
|
|
|
134
124
|
|
|
135
125
|
const requesterAddress = await iexec.wallet.getAddress();
|
|
136
126
|
|
|
137
|
-
let userVoucher;
|
|
138
|
-
if (vUseVoucher) {
|
|
139
|
-
try {
|
|
140
|
-
userVoucher = await iexec.voucher.showUserVoucher(requesterAddress);
|
|
141
|
-
checkUserVoucher({ userVoucher });
|
|
142
|
-
} catch (err) {
|
|
143
|
-
if (err?.message?.startsWith('No Voucher found for address')) {
|
|
144
|
-
throw new Error(
|
|
145
|
-
'Oops, it seems your wallet is not associated with any voucher. Check on https://builder.iex.ec/'
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
throw err;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
127
|
try {
|
|
153
128
|
// Fetch app order first to determine TEE framework
|
|
154
129
|
const apporder = await iexec.orderbook
|
|
155
130
|
.fetchAppOrderbook({
|
|
156
|
-
app:
|
|
131
|
+
app: vDappAddress,
|
|
157
132
|
minTag: ['tee'],
|
|
158
|
-
workerpool:
|
|
133
|
+
workerpool: vWorkerpoolAddress,
|
|
159
134
|
})
|
|
160
135
|
.then((appOrderbook) => {
|
|
161
136
|
const desiredPriceAppOrderbook = appOrderbook.orders.filter(
|
|
@@ -176,7 +151,7 @@ export const sendEmail = async ({
|
|
|
176
151
|
iexec.orderbook
|
|
177
152
|
.fetchDatasetOrderbook({
|
|
178
153
|
dataset: vDatasetAddress,
|
|
179
|
-
app:
|
|
154
|
+
app: vDappAddress,
|
|
180
155
|
requester: requesterAddress,
|
|
181
156
|
})
|
|
182
157
|
.then((datasetOrderbook) => {
|
|
@@ -203,21 +178,19 @@ export const sendEmail = async ({
|
|
|
203
178
|
Promise.all([
|
|
204
179
|
// for app
|
|
205
180
|
iexec.orderbook.fetchWorkerpoolOrderbook({
|
|
206
|
-
workerpool:
|
|
207
|
-
app:
|
|
181
|
+
workerpool: vWorkerpoolAddress,
|
|
182
|
+
app: vDappAddress,
|
|
208
183
|
dataset: vDatasetAddress,
|
|
209
|
-
requester: requesterAddress,
|
|
210
|
-
isRequesterStrict: useVoucher, // If voucher, we only want user specific orders
|
|
184
|
+
requester: requesterAddress,
|
|
211
185
|
minTag: workerpoolMinTag,
|
|
212
186
|
category: 0,
|
|
213
187
|
}),
|
|
214
188
|
// for app whitelist
|
|
215
189
|
iexec.orderbook.fetchWorkerpoolOrderbook({
|
|
216
|
-
workerpool:
|
|
190
|
+
workerpool: vWorkerpoolAddress,
|
|
217
191
|
app: vDappWhitelistAddress,
|
|
218
192
|
dataset: vDatasetAddress,
|
|
219
|
-
requester: requesterAddress,
|
|
220
|
-
isRequesterStrict: useVoucher, // If voucher, we only want user specific orders
|
|
193
|
+
requester: requesterAddress,
|
|
221
194
|
minTag: workerpoolMinTag,
|
|
222
195
|
category: 0,
|
|
223
196
|
}),
|
|
@@ -229,8 +202,6 @@ export const sendEmail = async ({
|
|
|
229
202
|
...workerpoolOrderbookForAppWhitelist.orders,
|
|
230
203
|
],
|
|
231
204
|
workerpoolMaxPrice: vWorkerpoolMaxPrice,
|
|
232
|
-
useVoucher: vUseVoucher,
|
|
233
|
-
userVoucher,
|
|
234
205
|
});
|
|
235
206
|
|
|
236
207
|
if (!desiredPriceWorkerpoolOrder) {
|
|
@@ -292,14 +263,14 @@ export const sendEmail = async ({
|
|
|
292
263
|
);
|
|
293
264
|
|
|
294
265
|
const requestorderToSign = await iexec.order.createRequestorder({
|
|
295
|
-
app:
|
|
266
|
+
app: vDappAddress,
|
|
296
267
|
category: workerpoolorder.category,
|
|
297
268
|
dataset: vDatasetAddress,
|
|
298
269
|
datasetmaxprice: datasetorder.datasetprice,
|
|
299
270
|
appmaxprice: apporder.appprice,
|
|
300
271
|
workerpoolmaxprice: workerpoolorder.workerpoolprice,
|
|
301
272
|
tag: ['tee'],
|
|
302
|
-
workerpool:
|
|
273
|
+
workerpool: vWorkerpoolAddress,
|
|
303
274
|
callback: CALLBACK_WEB3MAIL,
|
|
304
275
|
params: {
|
|
305
276
|
iexec_secrets: {
|
|
@@ -312,15 +283,12 @@ export const sendEmail = async ({
|
|
|
312
283
|
const requestorder = await iexec.order.signRequestorder(requestorderToSign);
|
|
313
284
|
|
|
314
285
|
// Match orders and compute task ID
|
|
315
|
-
const { dealid: dealId } = await iexec.order.matchOrders(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
},
|
|
322
|
-
{ useVoucher: vUseVoucher }
|
|
323
|
-
);
|
|
286
|
+
const { dealid: dealId } = await iexec.order.matchOrders({
|
|
287
|
+
apporder: apporder,
|
|
288
|
+
datasetorder: datasetorder,
|
|
289
|
+
workerpoolorder: workerpoolorder,
|
|
290
|
+
requestorder: requestorder,
|
|
291
|
+
});
|
|
324
292
|
|
|
325
293
|
const taskId = await iexec.deal.computeTaskId(dealId, 0);
|
|
326
294
|
|
|
@@ -2,7 +2,7 @@ import { NULL_ADDRESS } from 'iexec/utils';
|
|
|
2
2
|
import { ValidationError } from 'yup';
|
|
3
3
|
import { handleIfProtocolError, WorkflowError } from '../utils/errors.js';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
addressSchema,
|
|
6
6
|
campaignRequestSchema,
|
|
7
7
|
throwIfMissing,
|
|
8
8
|
} from '../utils/validators.js';
|
|
@@ -17,7 +17,7 @@ export type SendEmailCampaign = typeof sendEmailCampaign;
|
|
|
17
17
|
|
|
18
18
|
export const sendEmailCampaign = async ({
|
|
19
19
|
dataProtector = throwIfMissing(),
|
|
20
|
-
|
|
20
|
+
workerpoolAddress = throwIfMissing(),
|
|
21
21
|
campaignRequest,
|
|
22
22
|
}: DataProtectorConsumer &
|
|
23
23
|
SendEmailCampaignParams): Promise<SendEmailCampaignResponse> => {
|
|
@@ -26,18 +26,18 @@ export const sendEmailCampaign = async ({
|
|
|
26
26
|
.label('campaignRequest')
|
|
27
27
|
.validateSync(campaignRequest) as CampaignRequest;
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const vWorkerpoolAddress = addressSchema()
|
|
30
30
|
.required()
|
|
31
|
-
.label('
|
|
32
|
-
.validateSync(
|
|
31
|
+
.label('workerpoolAddress')
|
|
32
|
+
.validateSync(workerpoolAddress);
|
|
33
33
|
|
|
34
34
|
if (
|
|
35
35
|
vCampaignRequest.workerpool !== NULL_ADDRESS &&
|
|
36
36
|
vCampaignRequest.workerpool.toLowerCase() !==
|
|
37
|
-
|
|
37
|
+
vWorkerpoolAddress.toLowerCase()
|
|
38
38
|
) {
|
|
39
39
|
throw new ValidationError(
|
|
40
|
-
"
|
|
40
|
+
"workerpoolAddress doesn't match campaignRequest workerpool"
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -45,7 +45,7 @@ export const sendEmailCampaign = async ({
|
|
|
45
45
|
// Process the prepared bulk request
|
|
46
46
|
const processBulkRequestResponse = await dataProtector.processBulkRequest({
|
|
47
47
|
bulkRequest: vCampaignRequest,
|
|
48
|
-
workerpool:
|
|
48
|
+
workerpool: vWorkerpoolAddress,
|
|
49
49
|
waitForResult: false,
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -57,13 +57,12 @@ export const sendEmailCampaign = async ({
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// Handle protocol errors - this will throw if it's an ApiCallError
|
|
60
|
-
|
|
61
|
-
handleIfProtocolError(error);
|
|
60
|
+
handleIfProtocolError(error as Error);
|
|
62
61
|
|
|
63
62
|
// For all other errors
|
|
64
63
|
throw new WorkflowError({
|
|
65
64
|
message: 'Failed to sendEmailCampaign',
|
|
66
|
-
errorCause: error,
|
|
65
|
+
errorCause: error as Error,
|
|
67
66
|
});
|
|
68
67
|
}
|
|
69
68
|
};
|