From 20625f5e6bcccad2f41e4827e349072c1f426a83 Mon Sep 17 00:00:00 2001 From: Benjamin LEVESQUE <14175665+benjlevesque@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:37:20 +0200 Subject: [PATCH 1/3] feat: payment-processor transaction overrides --- .../src/payment/erc20-proxy.ts | 7 +++++ .../src/payment/eth-input-data.ts | 4 +++ .../payment-processor/src/payment/index.ts | 7 +++-- .../src/payment/transaction-overrides.ts | 4 +++ .../test/payment/erc20-proxy.test.ts | 30 +++++++++++++++++++ .../test/payment/eth-input-data.test.ts | 16 ++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 packages/payment-processor/src/payment/transaction-overrides.ts diff --git a/packages/payment-processor/src/payment/erc20-proxy.ts b/packages/payment-processor/src/payment/erc20-proxy.ts index e549897ff6..3580aeb512 100644 --- a/packages/payment-processor/src/payment/erc20-proxy.ts +++ b/packages/payment-processor/src/payment/erc20-proxy.ts @@ -7,6 +7,7 @@ import { ClientTypes, PaymentTypes } from '@requestnetwork/types'; import { ERC20Contract } from '../contracts/Erc20Contract'; import { Erc20ProxyContract } from '../contracts/Erc20ProxyContract'; +import { ITransactionOverrides } from './transaction-overrides'; import { getAmountToPay, getNetworkProvider, @@ -21,11 +22,13 @@ import { * @param request * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. + * @param overrides optionnally, override default transaction values, like gas. */ export async function payErc20ProxyRequest( request: ClientTypes.IRequestData, signerOrProvider: Web3Provider | Signer = getProvider(), amount?: BigNumberish, + overrides?: ITransactionOverrides, ): Promise { const encodedTx = encodePayErc20Request(request, signerOrProvider, amount); const proxyAddress = erc20ProxyArtifact.getAddress(request.currencyInfo.network!); @@ -34,6 +37,7 @@ export async function payErc20ProxyRequest( data: encodedTx, to: proxyAddress, value: 0, + ...overrides, }); return tx; } @@ -92,10 +96,12 @@ export async function hasErc20Approval( * @param request request to pay * @param account account that will be used to pay the request * @param provider the web3 provider. Defaults to Etherscan. + * @param overrides optionnally, override default transaction values, like gas. */ export async function approveErc20( request: ClientTypes.IRequestData, signerOrProvider: Web3Provider | Signer = getProvider(), + overrides?: ITransactionOverrides, ): Promise { const encodedTx = encodeApproveErc20(request, signerOrProvider); const signer = getSigner(signerOrProvider); @@ -104,6 +110,7 @@ export async function approveErc20( data: encodedTx, to: tokenAddress, value: 0, + ...overrides, }); return tx; } diff --git a/packages/payment-processor/src/payment/eth-input-data.ts b/packages/payment-processor/src/payment/eth-input-data.ts index 7d75fd4bc3..5e1445856f 100644 --- a/packages/payment-processor/src/payment/eth-input-data.ts +++ b/packages/payment-processor/src/payment/eth-input-data.ts @@ -4,6 +4,7 @@ import { BigNumberish } from 'ethers/utils'; import { ClientTypes, PaymentTypes } from '@requestnetwork/types'; +import { ITransactionOverrides } from './transaction-overrides'; import { getAmountToPay, getProvider, @@ -17,11 +18,13 @@ import { * @param request the request to pay * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. + * @param overrides optionnally, override default transaction values, like gas. */ export async function payEthInputDataRequest( request: ClientTypes.IRequestData, signerOrProvider: Web3Provider | Signer = getProvider(), amount?: BigNumberish, + overrides?: ITransactionOverrides, ): Promise { validateRequest(request, PaymentTypes.PAYMENT_NETWORK_ID.ETH_INPUT_DATA); const signer = getSigner(signerOrProvider); @@ -33,6 +36,7 @@ export async function payEthInputDataRequest( data: `0x${paymentReference}`, to: paymentAddress, value: amountToPay, + ...overrides, }); return tx; } diff --git a/packages/payment-processor/src/payment/index.ts b/packages/payment-processor/src/payment/index.ts index 86b2af1f0e..7c458991e8 100644 --- a/packages/payment-processor/src/payment/index.ts +++ b/packages/payment-processor/src/payment/index.ts @@ -7,6 +7,7 @@ import { ClientTypes, ExtensionTypes } from '@requestnetwork/types'; import { getBtcPaymentUrl } from './btc-address-based'; import { _getErc20PaymentUrl, getErc20Balance, payErc20ProxyRequest } from './erc20-proxy'; import { _getEthPaymentUrl, payEthInputDataRequest } from './eth-input-data'; +import { ITransactionOverrides } from './transaction-overrides'; import { getNetworkProvider, getProvider, getSigner } from './utils'; const getPaymentNetwork = (request: ClientTypes.IRequestData): ExtensionTypes.ID | undefined => { @@ -31,19 +32,21 @@ export class UnsupportedNetworkError extends Error { * @param request the request to pay. * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. + * @param overrides optionnally, override default transaction values, like gas. */ export async function payRequest( request: ClientTypes.IRequestData, signerOrProvider: Web3Provider | Signer = getProvider(), amount?: BigNumberish, + overrides?: ITransactionOverrides, ): Promise { const signer = getSigner(signerOrProvider); const paymentNetwork = getPaymentNetwork(request); switch (paymentNetwork) { case ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT: - return payErc20ProxyRequest(request, signer, amount); + return payErc20ProxyRequest(request, signer, amount, overrides); case ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA: - return payEthInputDataRequest(request, signer, amount); + return payEthInputDataRequest(request, signer, amount, overrides); default: throw new UnsupportedNetworkError(paymentNetwork); } diff --git a/packages/payment-processor/src/payment/transaction-overrides.ts b/packages/payment-processor/src/payment/transaction-overrides.ts new file mode 100644 index 0000000000..ae62402b0e --- /dev/null +++ b/packages/payment-processor/src/payment/transaction-overrides.ts @@ -0,0 +1,4 @@ +import { TransactionRequest } from 'ethers/providers'; + +/** Custom values to pass to transcaction */ +export interface ITransactionOverrides extends Omit {} diff --git a/packages/payment-processor/test/payment/erc20-proxy.test.ts b/packages/payment-processor/test/payment/erc20-proxy.test.ts index 3101c124c0..a10736530f 100644 --- a/packages/payment-processor/test/payment/erc20-proxy.test.ts +++ b/packages/payment-processor/test/payment/erc20-proxy.test.ts @@ -30,6 +30,7 @@ import { getRequestPaymentValues } from '../../src/payment/utils'; const expect = chai.expect; chai.use(chaiAsPromised); chai.use(spies); +const sandbox = chai.spy.sandbox(); const erc20ContractAddress = '0x9FBDa871d559710256a2502A2517b794B482Db40'; @@ -96,6 +97,20 @@ describe('getErc20Balance', () => { }); describe('hasErc20Approval & approveErc20', () => { + it('should consider override parameters', async () => { + const spy = sandbox.on(wallet, 'sendTransaction', () => 0); + await approveErc20(validRequest, wallet, { + gasPrice: '20000000000', + }); + expect(spy).to.have.been.called.with({ + data: + '0x095ea7b30000000000000000000000002c2b9c9a4a25e24b174f26114e8926a9f2128fe4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + gasPrice: '20000000000', + to: '0x9FBDa871d559710256a2502A2517b794B482Db40', + value: 0, + }); + sandbox.restore(); + }); it('can check and approve', async () => { // use another address so it doesn't mess with other tests. const otherWallet = new Wallet( @@ -145,6 +160,21 @@ describe('payErc20ProxyRequest', () => { ); }); + it('should consider override parameters', async () => { + const spy = sandbox.on(wallet, 'sendTransaction', () => 0); + await payErc20ProxyRequest(validRequest, wallet, undefined, { + gasPrice: '20000000000', + }); + expect(spy).to.have.been.called.with({ + data: + '0x0784bca30000000000000000000000009fbda871d559710256a2502a2517b794b482db40000000000000000000000000f17f52151ebef6c7334fad080c5704d77216b73200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000886dfbccad783599a000000000000000000000000000000000000000000000000', + gasPrice: '20000000000', + to: '0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4', + value: 0, + }); + sandbox.restore(); + }); + it('should pay an ERC20 request', async () => { // first approve the contract const approvalTx = await approveErc20(validRequest, wallet); diff --git a/packages/payment-processor/test/payment/eth-input-data.test.ts b/packages/payment-processor/test/payment/eth-input-data.test.ts index 83958e88c9..678aa62b88 100644 --- a/packages/payment-processor/test/payment/eth-input-data.test.ts +++ b/packages/payment-processor/test/payment/eth-input-data.test.ts @@ -17,6 +17,7 @@ import Utils from '@requestnetwork/utils'; import { _getEthPaymentUrl, payEthInputDataRequest } from '../../src/payment/eth-input-data'; import { getRequestPaymentValues } from '../../src/payment/utils'; +import { BigNumber } from 'ethers/utils'; // tslint:disable: no-unused-expression // tslint:disable: await-promise @@ -24,6 +25,7 @@ import { getRequestPaymentValues } from '../../src/payment/utils'; const expect = chai.expect; chai.use(chaiAsPromised); chai.use(spies); +const sandbox = chai.spy.sandbox(); const mnemonic = 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat'; const paymentAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; @@ -106,6 +108,20 @@ describe('payEthInputDataRequest', () => { ); }); + it('should consider override parameters', async () => { + const spy = sandbox.on(wallet, 'sendTransaction', () => 0); + await payEthInputDataRequest(validRequest, wallet, undefined, { + gasPrice: '20000000001', + }); + expect(spy).to.have.been.called.with({ + data: '0x86dfbccad783599a', + gasPrice: '20000000001', + to: '0xf17f52151EbEF6C7334FAD080c5704D77216b732', + value: new BigNumber(1), + }); + sandbox.restore(); + }); + it('processes a payment for a pn-eth-input-data request', async () => { const balanceBefore = await wallet.getBalance(); expect(balanceBefore.gt(0)); From 1055946c792b0170aee4c070f75e5aed3763eee5 Mon Sep 17 00:00:00 2001 From: Benjamin LEVESQUE <14175665+benjlevesque@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:07:32 +0200 Subject: [PATCH 2/3] typos --- packages/payment-processor/src/payment/erc20-proxy.ts | 4 ++-- packages/payment-processor/src/payment/eth-input-data.ts | 2 +- packages/payment-processor/src/payment/index.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/payment-processor/src/payment/erc20-proxy.ts b/packages/payment-processor/src/payment/erc20-proxy.ts index 3580aeb512..43b405abc6 100644 --- a/packages/payment-processor/src/payment/erc20-proxy.ts +++ b/packages/payment-processor/src/payment/erc20-proxy.ts @@ -22,7 +22,7 @@ import { * @param request * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. - * @param overrides optionnally, override default transaction values, like gas. + * @param overrides optionally, override default transaction values, like gas. */ export async function payErc20ProxyRequest( request: ClientTypes.IRequestData, @@ -96,7 +96,7 @@ export async function hasErc20Approval( * @param request request to pay * @param account account that will be used to pay the request * @param provider the web3 provider. Defaults to Etherscan. - * @param overrides optionnally, override default transaction values, like gas. + * @param overrides optionally, override default transaction values, like gas. */ export async function approveErc20( request: ClientTypes.IRequestData, diff --git a/packages/payment-processor/src/payment/eth-input-data.ts b/packages/payment-processor/src/payment/eth-input-data.ts index 5e1445856f..f98fc3afb6 100644 --- a/packages/payment-processor/src/payment/eth-input-data.ts +++ b/packages/payment-processor/src/payment/eth-input-data.ts @@ -18,7 +18,7 @@ import { * @param request the request to pay * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. - * @param overrides optionnally, override default transaction values, like gas. + * @param overrides optionally, override default transaction values, like gas. */ export async function payEthInputDataRequest( request: ClientTypes.IRequestData, diff --git a/packages/payment-processor/src/payment/index.ts b/packages/payment-processor/src/payment/index.ts index 7c458991e8..bfd14e28db 100644 --- a/packages/payment-processor/src/payment/index.ts +++ b/packages/payment-processor/src/payment/index.ts @@ -32,7 +32,7 @@ export class UnsupportedNetworkError extends Error { * @param request the request to pay. * @param signerOrProvider the Web3 provider, or signer. Defaults to window.ethereum. * @param amount optionally, the amount to pay. Defaults to remaining amount of the request. - * @param overrides optionnally, override default transaction values, like gas. + * @param overrides optionally, override default transaction values, like gas. */ export async function payRequest( request: ClientTypes.IRequestData, From 89d40034542f62398ca7d12d80daeeaa273b97d1 Mon Sep 17 00:00:00 2001 From: Benjamin LEVESQUE <14175665+benjlevesque@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:20:09 +0200 Subject: [PATCH 3/3] typo --- packages/payment-processor/src/payment/transaction-overrides.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/payment-processor/src/payment/transaction-overrides.ts b/packages/payment-processor/src/payment/transaction-overrides.ts index ae62402b0e..930f09a154 100644 --- a/packages/payment-processor/src/payment/transaction-overrides.ts +++ b/packages/payment-processor/src/payment/transaction-overrides.ts @@ -1,4 +1,4 @@ import { TransactionRequest } from 'ethers/providers'; -/** Custom values to pass to transcaction */ +/** Custom values to pass to transaction */ export interface ITransactionOverrides extends Omit {}