Skip to content

Commit 43baa37

Browse files
committed
add batch fee amount USD to batch payment processor and its tests
1 parent 42913a7 commit 43baa37

File tree

2 files changed

+117
-33
lines changed

2 files changed

+117
-33
lines changed

packages/payment-processor/src/payment/batch-conversion-proxy.ts

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ import { IPreparedTransaction } from './prepared-transaction';
2121
import { EnrichedRequest, IConversionPaymentSettings } from './index';
2222
import { checkRequestAndGetPathAndCurrency } from './any-to-erc20-proxy';
2323
import { checkErc20Allowance, encodeApproveAnyErc20 } from './erc20';
24-
import { BATCH_PAYMENT_NETWORK_ID } from '@requestnetwork/types/dist/payment-types';
24+
import { BATCH_PAYMENT_NETWORK_ID, RequestDetail } from '@requestnetwork/types/dist/payment-types';
2525
import { IState } from 'types/dist/extension-types';
26-
import { CurrencyInput, isERC20Currency, isISO4217Currency } from '@requestnetwork/currency';
26+
import {
27+
CurrencyInput,
28+
isERC20Currency,
29+
isISO4217Currency,
30+
CurrencyManager,
31+
} from '@requestnetwork/currency';
32+
33+
const currencyManager = CurrencyManager.getDefault();
2734

2835
/**
2936
* Processes a transaction to pay a batch of requests with an ERC20 currency
@@ -33,6 +40,9 @@ import { CurrencyInput, isERC20Currency, isISO4217Currency } from '@requestnetwo
3340
* @param enrichedRequests List of EnrichedRequests to pay
3441
* @param version The version of the batch conversion proxy
3542
* @param signerOrProvider The Web3 provider, or signer. Defaults to window.ethereum.
43+
* @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduce gas consumption.
44+
* It can be useful to set it to false if the total amount of the batch is important.
45+
* Check the value of batchFeeAmountUSDLimit of the batch proxy deployed.
3646
* @param overrides Optionally, override default transaction values, like gas.
3747
* @dev We only implement batchPayments using two ERC20 functions:
3848
* batchMultiERC20ConversionPayments, and batchMultiERC20Payments.
@@ -41,25 +51,34 @@ export async function payBatchConversionProxyRequest(
4151
enrichedRequests: EnrichedRequest[],
4252
version: string,
4353
signerOrProvider: providers.Provider | Signer = getProvider(),
54+
skipFeeUSDLimit = true,
4455
overrides?: ITransactionOverrides,
4556
): Promise<ContractTransaction> {
46-
const { data, to, value } = prepareBatchConversionPaymentTransaction(enrichedRequests, version);
57+
const { data, to, value } = prepareBatchConversionPaymentTransaction(
58+
enrichedRequests,
59+
version,
60+
skipFeeUSDLimit,
61+
);
4762
const signer = getSigner(signerOrProvider);
4863
return signer.sendTransaction({ data, to, value, ...overrides });
4964
}
5065

5166
/**
5267
* Prepares a transaction to pay a batch of requests with an ERC20 currency
53-
* that is different from the request currency (eg. fiat)
54-
* it can be used with a Multisig contract.
68+
* that can be different from the request currency (eg. fiat).
69+
* It can be used with a Multisig contract.
5570
* @param enrichedRequests List of EnrichedRequests to pay
5671
* @param version The version of the batch conversion proxy
72+
* @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduce gas consumption.
73+
* It can be useful to set it to false if the total amount of the batch is important.
74+
* Check the value of batchFeeAmountUSDLimit of the batch proxy deployed.
5775
*/
5876
export function prepareBatchConversionPaymentTransaction(
5977
enrichedRequests: EnrichedRequest[],
6078
version: string,
79+
skipFeeUSDLimit = true,
6180
): IPreparedTransaction {
62-
const encodedTx = encodePayBatchConversionRequest(enrichedRequests);
81+
const encodedTx = encodePayBatchConversionRequest(enrichedRequests, skipFeeUSDLimit);
6382
const proxyAddress = getBatchConversionProxyAddress(enrichedRequests[0].request, version);
6483
return {
6584
data: encodedTx,
@@ -70,11 +89,17 @@ export function prepareBatchConversionPaymentTransaction(
7089

7190
/**
7291
* Encodes a transaction to pay a batch of requests with an ERC20 currency
73-
* that is different from the request currency (eg. fiat)
92+
* that can be different from the request currency (eg. fiat).
7493
* It can be used with a Multisig contract.
7594
* @param enrichedRequests List of EnrichedRequests to pay
95+
* @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduce gas consumption.
96+
* It can be useful to set it to false if the total amount of the batch is important.
97+
* Check the value of batchFeeAmountUSDLimit of the batch proxy deployed.
7698
*/
77-
export function encodePayBatchConversionRequest(enrichedRequests: EnrichedRequest[]): string {
99+
export function encodePayBatchConversionRequest(
100+
enrichedRequests: EnrichedRequest[],
101+
skipFeeUSDLimit = true,
102+
): string {
78103
const { feeAddress } = getRequestPaymentValues(enrichedRequests[0].request);
79104

80105
const firstNetwork = getPnAndNetwork(enrichedRequests[0].request)[1];
@@ -101,7 +126,7 @@ export function encodePayBatchConversionRequest(enrichedRequests: EnrichedReques
101126
) {
102127
throw new Error(`wrong request currencyInfo type`);
103128
}
104-
requestDetailsERC20Conversion.push(getInputConversionDetail(enrichedRequest));
129+
requestDetailsERC20Conversion.push(getInputRequestDetailERC20Conversion(enrichedRequest));
105130
} else if (
106131
enrichedRequest.paymentNetworkId === BATCH_PAYMENT_NETWORK_ID.BATCH_MULTI_ERC20_PAYMENTS
107132
) {
@@ -136,14 +161,24 @@ export function encodePayBatchConversionRequest(enrichedRequests: EnrichedReques
136161
});
137162
}
138163

164+
const pathsToUSD = getPathsToUSD(
165+
[...requestDetailsERC20Conversion, ...requestDetailsERC20NoConversion],
166+
firstNetwork,
167+
skipFeeUSDLimit,
168+
);
169+
139170
const proxyContract = BatchConversionPayments__factory.createInterface();
140171
return proxyContract.encodeFunctionData('batchPayments', [
141172
metaDetails,
142-
[],
173+
skipFeeUSDLimit ? [] : pathsToUSD,
143174
feeAddress || constants.AddressZero,
144175
]);
145176
}
146177

178+
/**
179+
* Get the ERC20 no conversion input requestDetail from a request, that can be used by the batch contract.
180+
* @param request The request to pay.
181+
*/
147182
function getInputRequestDetailERC20NoConversion(
148183
request: ClientTypes.IRequestData,
149184
): PaymentTypes.RequestDetail {
@@ -157,17 +192,19 @@ function getInputRequestDetailERC20NoConversion(
157192
requestAmount: getAmountToPay(request).toString(),
158193
path: [tokenAddress],
159194
paymentReference: `0x${paymentReference}`,
160-
feeAmount: feeAmount || '0',
161-
maxToSpend: '',
162-
maxRateTimespan: '',
195+
feeAmount: feeAmount?.toString() || '0',
196+
maxToSpend: '0',
197+
maxRateTimespan: '0',
163198
};
164199
}
165200

166201
/**
167-
* Get the conversion detail values from one enriched request
168-
* @param enrichedRequest The enrichedRequest to pay
202+
* Get the ERC20 conversion input requestDetail from an enriched request, that can be used by the batch contract.
203+
* @param enrichedRequest The enrichedRequest to pay.
169204
*/
170-
function getInputConversionDetail(enrichedRequest: EnrichedRequest): PaymentTypes.RequestDetail {
205+
function getInputRequestDetailERC20Conversion(
206+
enrichedRequest: EnrichedRequest,
207+
): PaymentTypes.RequestDetail {
171208
const paymentSettings = enrichedRequest.paymentSettings;
172209
if (!paymentSettings) throw Error('the enrichedRequest has no paymentSettings');
173210

@@ -198,7 +235,40 @@ function getInputConversionDetail(enrichedRequest: EnrichedRequest): PaymentType
198235
}
199236

200237
/**
201-
*
238+
* Get the list of conversion paths from tokens to the USD address through currencyManager.
239+
* @param requestDetails List of ERC20 requests to pay.
240+
* @param network The network targeted.
241+
* @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduce gas consumption.
242+
* It can be useful to set it to false if the total amount of the batch is important.
243+
* Check the value of batchFeeAmountUSDLimit of the batch proxy deployed.
244+
*/
245+
function getPathsToUSD(
246+
requestDetails: RequestDetail[],
247+
network: string,
248+
skipFeeUSDLimit: boolean,
249+
): string[][] {
250+
const pathsToUSD: Array<string>[] = [];
251+
if (!skipFeeUSDLimit) {
252+
const USDCurrency = currencyManager.fromSymbol('USD');
253+
// token's addresses paid with the batch
254+
const tokenAddresses: Array<string> = [];
255+
for (const requestDetail of requestDetails) {
256+
const tokenAddress = requestDetail.path[requestDetail.path.length - 1];
257+
// Check token to only unique paths token to USD.
258+
if (!tokenAddresses.includes(tokenAddress)) {
259+
tokenAddresses.push(tokenAddress);
260+
const tokenCurrency = currencyManager.fromAddress(tokenAddress);
261+
const pathToUSD = currencyManager.getConversionPath(tokenCurrency!, USDCurrency!, network);
262+
if (pathToUSD) {
263+
pathsToUSD.push(pathToUSD);
264+
}
265+
}
266+
}
267+
}
268+
return pathsToUSD;
269+
}
270+
271+
/**
202272
* @param network The network targeted
203273
* @param version The version of the batch conversion proxy
204274
* @returns

0 commit comments

Comments
 (0)