Skip to content

Commit

Permalink
feat(processor): any-declarative payment in NEAR (#1428)
Browse files Browse the repository at this point in the history
  • Loading branch information
yomarion authored Jul 15, 2024
1 parent 9558a49 commit a23a847
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 32 deletions.
5 changes: 2 additions & 3 deletions packages/payment-processor/src/payment/any-to-erc20-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { padAmountForChainlink } from '@requestnetwork/payment-detection';
import { IPreparedTransaction } from './prepared-transaction';
import { IConversionPaymentSettings } from './index';
import { validatePaymentReference } from '../utils/validation';

/**
* Processes a transaction to pay a request with an ERC20 currency that is different from the request currency (eg. fiat).
Expand Down Expand Up @@ -153,9 +154,7 @@ function prepareAnyToErc20Arguments(

const { paymentReference, paymentAddress, feeAddress, feeAmount, maxRateTimespan } =
getRequestPaymentValues(request);
if (!paymentReference) {
throw new Error('paymentReference is missing');
}
validatePaymentReference(paymentReference);
const amountToPay = padAmountForChainlink(getAmountToPay(request, amount), requestCurrency);
const feeToPay = padAmountForChainlink(feeAmountOverride || feeAmount || 0, requestCurrency);
return {
Expand Down
40 changes: 40 additions & 0 deletions packages/payment-processor/src/payment/near-amount-with-ref.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { BigNumberish } from 'ethers';
import { WalletConnection } from 'near-api-js';

import { CurrencyTypes } from '@requestnetwork/types';

import { INearTransactionCallback, processNearPayment } from './utils-near';
import { NearChains } from '@requestnetwork/currency';

/**
* Processes a transaction to make a payment in NEAR token with a reference.
*
* @notice This is used to pay a declarative request, with low-level arguments.
*
* @param paymentAddress must be a valid NEAR address on the given network.
* @param network e.g. 'near'
* @param paymentReference used to index payments.
* @param walletConnection the Near provider.
* @param amount amount to pay, in NEAR tokens.
*/
// FIXME: We could improve the method's interface by enforcing a type on `paymentInfo` for declarative requests.
export async function payNearAmountWithReference(
paymentAddress: string,
paymentReference: string,
network: CurrencyTypes.NearChainName,
walletConnection: WalletConnection,
amount: BigNumberish,
callback?: INearTransactionCallback,
): Promise<void> {
NearChains.assertChainSupported(network);

return processNearPayment(
walletConnection,
network,
amount,
paymentAddress,
paymentReference,
'0.2.0',
callback,
);
}
13 changes: 4 additions & 9 deletions packages/payment-processor/src/payment/near-conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import {
import { INearTransactionCallback, processNearPaymentWithConversion } from './utils-near';
import { IConversionPaymentSettings } from '.';
import { CurrencyManager, NearChains, UnsupportedCurrencyError } from '@requestnetwork/currency';
import { validatePaymentReference } from '../utils/validation';

/**
* Processes the transaction to pay a request in NEAR with on-chain conversion.
* @param request the request to pay
* @param walletConnection the Web3 provider, or signer. Defaults to window.ethereum.
* @param amount optionally, the amount to pay. Defaults to remaining amount of the request.
* @param walletConnection the Near provider.
* @param amount optionally, the amount to pay in request currency. Defaults to remaining amount of the request.
*/
export async function payNearConversionRequest(
request: ClientTypes.IRequestData,
Expand All @@ -37,13 +38,7 @@ export async function payNearConversionRequest(
throw new UnsupportedCurrencyError(request.currencyInfo);
}

if (!paymentReference) {
throw new Error('Cannot pay without a paymentReference');
}

if (!network || !NearChains.isChainSupported(network)) {
throw new Error('Should be a Near network');
}
validatePaymentReference(paymentReference);
NearChains.assertChainSupported(network);

const amountToPay = getAmountToPay(request, amount).toString();
Expand Down
9 changes: 3 additions & 6 deletions packages/payment-processor/src/payment/near-fungible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import {
processNearFungiblePayment,
} from './utils-near';
import { NearChains } from '@requestnetwork/currency';
import { validatePaymentReference } from '../utils/validation';

/**
* Processes the transaction to pay a request in fungible token on NEAR with fee (Erc20FeeProxy).
* @param request the request to pay
* @param walletConnection the Near provider.
*/
export async function payNearFungibleRequest(
request: ClientTypes.IRequestData,
Expand All @@ -27,13 +29,8 @@ export async function payNearFungibleRequest(
const { paymentReference, paymentAddress, feeAddress, feeAmount, network } =
getRequestPaymentValues(request);

if (!paymentReference) {
throw new Error('Cannot pay without a paymentReference');
}
validatePaymentReference(paymentReference);

if (!network || !NearChains.isChainSupported(network)) {
throw new Error('Should be a Near network');
}
NearChains.assertChainSupported(network);

const amountToPay = getAmountToPay(request, amount).toString();
Expand Down
7 changes: 3 additions & 4 deletions packages/payment-processor/src/payment/near-input-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import {
} from './utils';
import { INearTransactionCallback, processNearPayment } from './utils-near';
import { NearChains } from '@requestnetwork/currency';
import { validatePaymentReference } from '../utils/validation';

/**
* processes the transaction to pay a Near request.
* @param request the request to pay
* @param walletConnection the Web3 provider, or signer. Defaults to window.ethereum.
* @param walletConnection the Near provider.
* @param amount optionally, the amount to pay. Defaults to remaining amount of the request.
*/
export async function payNearInputDataRequest(
Expand All @@ -34,9 +35,7 @@ export async function payNearInputDataRequest(
const { paymentReference, paymentAddress } = getRequestPaymentValues(request);
const amountToPay = getAmountToPay(request, amount).toString();
const version = getPaymentExtensionVersion(request);
if (!paymentReference) {
throw new Error('Cannot pay without a paymentReference');
}
validatePaymentReference(paymentReference);

return processNearPayment(
walletConnection,
Expand Down
16 changes: 7 additions & 9 deletions packages/payment-processor/src/payment/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,21 +353,19 @@ export function validateERC20TransferableReceivable(
}

/**
* Computes the amount to pay.
* If `amount` is specified, it will return it.
* Otherwise, it will return the amount left to pay in the request.
* It returns the amount left to pay in the request, unless an amount is specified.
*
* @param request the request to pay
* @param amount the optional amount to pay.
* @param request the request to pay.
* @param amount optionally override the returned amount to pay, in request currency.
* @returns the amount to pay, in request currency.
*/
export function getAmountToPay(
request: ClientTypes.IRequestData,
amount?: BigNumberish,
): BigNumber {
const amountToPay =
amount === undefined
? BigNumber.from(request.expectedAmount).sub(request.balance?.balance || 0)
: BigNumber.from(amount);
const amountToPay = amount
? BigNumber.from(amount)
: BigNumber.from(request.expectedAmount).sub(request.balance?.balance || 0);

if (amountToPay.lt(0)) {
throw new Error('cannot pay a negative amount');
Expand Down
8 changes: 8 additions & 0 deletions packages/payment-processor/src/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** Validates the presence of the payment reference for payment. */
export function validatePaymentReference(
paymentReference?: string,
): asserts paymentReference is string {
if (!paymentReference) {
throw new Error('Cannot pay without a paymentReference');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ describe('payNearWithConversionRequest', () => {

await expect(
payNearConversionRequest(invalidRequest, mockedNearWalletConnection, conversionSettings),
).rejects.toThrowError('Should be a Near network');
).rejects.toThrowError('Unsupported chain unknown-network');
expect(paymentSpy).not.toHaveBeenCalled();
});
});

0 comments on commit a23a847

Please sign in to comment.