Skip to content

Commit 8b851e7

Browse files
authored
feat: near conversion payment detector (#920)
1 parent 59d222f commit 8b851e7

File tree

13 files changed

+447
-28
lines changed

13 files changed

+447
-28
lines changed

packages/advanced-logic/src/extensions/payment-network/any-to-near.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ export default class AnyToNearPaymentNetwork extends AnyToNativeTokenPaymentNetw
200200
if (!currency) {
201201
throw new UnsupportedCurrencyError(request.currency);
202202
}
203-
console.log(network);
204-
console.log(currency);
205203
if (!this.currencyManager.supportsConversion(currency, network)) {
206204
throw new Error(
207205
`The currency (${request.currency.value}) of the request is not supported for this payment network.`,

packages/payment-detection/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
getPaymentNetworkExtension,
1717
getPaymentReference,
1818
} from './utils';
19-
import { NearNativeTokenPaymentDetector } from './near-detector';
19+
import { NearNativeTokenPaymentDetector, NearConversionNativeTokenPaymentDetector } from './near';
2020
import { FeeReferenceBasedDetector } from './fee-reference-based-detector';
2121
import { SuperFluidPaymentDetector } from './erc777/superfluid-detector';
2222
import { EscrowERC20InfoRetriever } from './erc20/escrow-info-retriever';
@@ -37,6 +37,7 @@ export {
3737
FeeReferenceBasedDetector,
3838
SuperFluidPaymentDetector,
3939
NearNativeTokenPaymentDetector,
40+
NearConversionNativeTokenPaymentDetector,
4041
EscrowERC20InfoRetriever,
4142
SuperFluidInfoRetriever,
4243
setProviderFactory,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { NearNativeTokenPaymentDetector } from './near-detector';
2+
export { NearConversionNativeTokenPaymentDetector } from './near-conversion-detector';
3+
export { NearConversionInfoRetriever } from './retrievers/near-conversion-info-retriever';
4+
export { NearInfoRetriever } from './retrievers/near-info-retriever';
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import {
2+
AdvancedLogicTypes,
3+
ExtensionTypes,
4+
PaymentTypes,
5+
RequestLogicTypes,
6+
} from '@requestnetwork/types';
7+
8+
import { AnyToAnyDetector } from '../any-to-any-detector';
9+
import { ICurrencyManager, UnsupportedCurrencyError } from '@requestnetwork/currency';
10+
import { NearConversionInfoRetriever } from './retrievers/near-conversion-info-retriever';
11+
12+
// interface of the object indexing the proxy contract version
13+
interface IProxyContractVersion {
14+
[version: string]: string;
15+
}
16+
17+
// the versions 0.1.0 and 0.2.0 have the same contracts
18+
const CONTRACT_ADDRESS_MAP: IProxyContractVersion = {
19+
['0.1.0']: '0.1.0',
20+
};
21+
22+
/**
23+
* Handle payment detection for NEAR native token payment with conversion
24+
*/
25+
export class NearConversionNativeTokenPaymentDetector extends AnyToAnyDetector<
26+
ExtensionTypes.PnAnyToEth.IAnyToEth,
27+
PaymentTypes.IETHPaymentEventParameters
28+
> {
29+
/**
30+
* @param extension The advanced logic payment network extension
31+
*/
32+
public constructor({
33+
advancedLogic,
34+
currencyManager,
35+
}: {
36+
advancedLogic: AdvancedLogicTypes.IAdvancedLogic;
37+
currencyManager: ICurrencyManager;
38+
}) {
39+
super(
40+
PaymentTypes.PAYMENT_NETWORK_ID.ANY_TO_NATIVE,
41+
advancedLogic.extensions.anyToNativeToken[0],
42+
currencyManager,
43+
);
44+
}
45+
46+
public static getContractName = (chainName: string, paymentNetworkVersion = '0.1.0'): string => {
47+
const version =
48+
NearConversionNativeTokenPaymentDetector.getVersionOrThrow(paymentNetworkVersion);
49+
const versionMap: Record<string, Record<string, string>> = {
50+
aurora: { '0.1.0': 'requestnetwork.conversion.near' },
51+
'aurora-testnet': {
52+
'0.1.0': 'dev-xxxxxxx',
53+
},
54+
};
55+
if (versionMap[chainName]?.[version]) {
56+
return versionMap[chainName][version];
57+
}
58+
throw Error(`Unconfigured chain '${chainName}' and version '${version}'.`);
59+
};
60+
61+
/**
62+
* Extracts the events for an address and a payment reference
63+
*
64+
* @param address Address to check
65+
* @param eventName Indicate if it is an address for payment or refund
66+
* @param requestCurrency The request currency
67+
* @param paymentReference The reference to identify the payment
68+
* @param paymentNetwork the payment network state
69+
* @returns The balance with events
70+
*/
71+
protected async extractEvents(
72+
eventName: PaymentTypes.EVENTS_NAMES,
73+
address: string | undefined,
74+
paymentReference: string,
75+
requestCurrency: RequestLogicTypes.ICurrency,
76+
paymentChain: string,
77+
paymentNetwork: ExtensionTypes.IState<ExtensionTypes.PnAnyToEth.ICreationParameters>,
78+
): Promise<PaymentTypes.AllNetworkRetrieverEvents<PaymentTypes.ETHPaymentNetworkEvent>> {
79+
if (!address) {
80+
return {
81+
paymentEvents: [],
82+
};
83+
}
84+
85+
const currency = this.currencyManager.fromStorageCurrency(requestCurrency);
86+
if (!currency) {
87+
throw new UnsupportedCurrencyError(requestCurrency.value);
88+
}
89+
90+
const infoRetriever = new NearConversionInfoRetriever(
91+
currency,
92+
paymentReference,
93+
address,
94+
NearConversionNativeTokenPaymentDetector.getContractName(
95+
paymentChain,
96+
paymentNetwork.version,
97+
),
98+
eventName,
99+
paymentChain,
100+
paymentNetwork.values.maxRateTimespan,
101+
);
102+
const paymentEvents = await infoRetriever.getTransferEvents();
103+
return {
104+
paymentEvents,
105+
};
106+
}
107+
108+
protected getPaymentChain(request: RequestLogicTypes.IRequest): string {
109+
const network = this.getPaymentExtension(request).values.network;
110+
if (!network) {
111+
throw Error(`request.extensions[${this.paymentNetworkId}].values.network must be defined`);
112+
}
113+
return network;
114+
}
115+
116+
protected static getVersionOrThrow = (paymentNetworkVersion: string): string => {
117+
if (!CONTRACT_ADDRESS_MAP[paymentNetworkVersion]) {
118+
throw Error(`Near payment detection not implemented for version ${paymentNetworkVersion}`);
119+
}
120+
return CONTRACT_ADDRESS_MAP[paymentNetworkVersion];
121+
};
122+
}

packages/payment-detection/src/near-detector.ts renamed to packages/payment-detection/src/near/near-detector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
RequestLogicTypes,
66
} from '@requestnetwork/types';
77

8-
import { ReferenceBasedDetector } from './reference-based-detector';
9-
import { NearInfoRetriever } from './near-info-retriever';
8+
import { ReferenceBasedDetector } from '../reference-based-detector';
9+
import { NearInfoRetriever } from './retrievers/near-info-retriever';
1010

1111
// interface of the object indexing the proxy contract version
1212
interface IProxyContractVersion {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { PaymentTypes } from '@requestnetwork/types';
2+
import { CurrencyDefinition } from 'currency/dist';
3+
import { NearInfoRetriever } from './near-info-retriever';
4+
5+
// FIXME#1: when Near subgraphes can retrieve a txHash, replace the custom IPaymentNetworkEvent with PaymentTypes.ETHPaymentNetworkEvent
6+
interface NearSubGraphPaymentEvent extends PaymentTypes.IETHPaymentEventParameters {
7+
receiptId: string;
8+
}
9+
10+
/**
11+
* Gets a list of transfer events for a set of Near payment details
12+
*/
13+
export class NearConversionInfoRetriever extends NearInfoRetriever {
14+
/**
15+
* @param paymentReference The reference to identify the payment
16+
* @param toAddress Address to check
17+
* @param eventName Indicate if it is an address for payment or refund
18+
* @param network The id of network we want to check
19+
*/
20+
constructor(
21+
protected requestCurrency: CurrencyDefinition,
22+
protected paymentReference: string,
23+
protected toAddress: string,
24+
protected proxyContractName: string,
25+
protected eventName: PaymentTypes.EVENTS_NAMES,
26+
protected network: string,
27+
protected maxRateTimespan: number = 0,
28+
) {
29+
super(paymentReference, toAddress, proxyContractName, eventName, network);
30+
}
31+
32+
public async getTransferEvents(): Promise<
33+
PaymentTypes.IPaymentNetworkEvent<NearSubGraphPaymentEvent>[]
34+
> {
35+
const payments = await this.client.GetNearConversionPayments({
36+
reference: this.paymentReference,
37+
to: this.toAddress,
38+
currency: this.requestCurrency.symbol,
39+
maxRateTimespan: this.maxRateTimespan,
40+
contractAddress: this.proxyContractName,
41+
});
42+
return payments.payments.map((p: any) => ({
43+
amount: p.amount,
44+
name: this.eventName,
45+
parameters: {
46+
block: p.block,
47+
feeAddress: p.feeAddress || undefined,
48+
feeAmount: p.feeAmount,
49+
feeAmountInCrypto: p.feeAmountInCrypto || undefined,
50+
amountInCrypto: p.amountInCrypto,
51+
to: this.toAddress,
52+
maxRateTimespan: p.maxRateTimespan?.toString(),
53+
from: p.from,
54+
gasUsed: p.gasUsed,
55+
gasPrice: p.gasPrice,
56+
receiptId: p.receiptId,
57+
currency: p.currency,
58+
},
59+
timestamp: Number(p.timestamp),
60+
}));
61+
}
62+
}

packages/payment-detection/src/near-info-retriever.ts renamed to packages/payment-detection/src/near/retrievers/near-info-retriever.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PaymentTypes } from '@requestnetwork/types';
2-
import { getTheGraphNearClient, TheGraphClient } from '.';
2+
import { getTheGraphNearClient, TheGraphClient } from '../../thegraph';
33

44
// FIXME#1: when Near subgraphes can retrieve a txHash, replace the custom IPaymentNetworkEvent with PaymentTypes.ETHPaymentNetworkEvent
55
interface NearSubGraphPaymentEvent extends PaymentTypes.IETHPaymentEventParameters {
@@ -10,33 +10,25 @@ interface NearSubGraphPaymentEvent extends PaymentTypes.IETHPaymentEventParamete
1010
* Gets a list of transfer events for a set of Near payment details
1111
*/
1212
export class NearInfoRetriever {
13-
private client: TheGraphClient<'near'>;
13+
protected client: TheGraphClient<'near'>;
1414
/**
1515
* @param paymentReference The reference to identify the payment
1616
* @param toAddress Address to check
1717
* @param eventName Indicate if it is an address for payment or refund
1818
* @param network The id of network we want to check
19+
*
1920
*/
2021
constructor(
21-
private paymentReference: string,
22-
private toAddress: string,
23-
private proxyContractName: string,
24-
private eventName: PaymentTypes.EVENTS_NAMES,
25-
private network: string,
22+
protected paymentReference: string,
23+
protected toAddress: string,
24+
protected proxyContractName: string,
25+
protected eventName: PaymentTypes.EVENTS_NAMES,
26+
protected network: string,
2627
) {
2728
if (this.network !== 'aurora' && this.network !== 'aurora-testnet') {
2829
throw new Error('Near input data info-retriever only works with Near mainnet and testnet');
2930
}
30-
if (this.network !== 'aurora') {
31-
// FIXME: remove this check and implement testnet detection once aurora-testnet subgraphes are available
32-
throw new Error('FIXME: getTransactionsFromNearSubGraph() only implemented for Near mainnet');
33-
}
3431
this.network = this.network.replace('aurora', 'near');
35-
if (this.proxyContractName !== 'requestnetwork.near') {
36-
throw new Error(
37-
`Proxy contract "${proxyContractName}" not supported by Near subgraph retriever`,
38-
);
39-
}
4032
this.client = getTheGraphNearClient(this.network as 'near' | 'near-testnet');
4133
}
4234

@@ -46,6 +38,7 @@ export class NearInfoRetriever {
4638
const payments = await this.client.GetNearPayments({
4739
reference: this.paymentReference,
4840
to: this.toAddress,
41+
contractAddress: this.proxyContractName,
4942
});
5043
return payments.payments.map((p) => ({
5144
amount: p.amount,

packages/payment-detection/src/payment-network-factory.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { SuperFluidPaymentDetector } from './erc777/superfluid-detector';
1616
import { EthInputDataPaymentDetector } from './eth/input-data';
1717
import { EthFeeProxyPaymentDetector } from './eth/fee-proxy-detector';
1818
import { AnyToERC20PaymentDetector } from './any/any-to-erc20-proxy';
19-
import { NearNativeTokenPaymentDetector } from './near-detector';
19+
import { NearConversionNativeTokenPaymentDetector, NearNativeTokenPaymentDetector } from './near';
2020
import { AnyToEthFeeProxyPaymentDetector } from './any/any-to-eth-proxy';
2121

2222
const PN_ID = PaymentTypes.PAYMENT_NETWORK_ID;
@@ -59,6 +59,7 @@ const anyCurrencyPaymentNetwork: IPaymentNetworkModuleByType = {
5959
[PN_ID.ANY_TO_ERC20_PROXY]: AnyToERC20PaymentDetector,
6060
[PN_ID.DECLARATIVE]: DeclarativePaymentDetector,
6161
[PN_ID.ANY_TO_ETH_PROXY]: AnyToEthFeeProxyPaymentDetector,
62+
[PN_ID.ANY_TO_NATIVE]: NearConversionNativeTokenPaymentDetector,
6263
};
6364

6465
/** Factory to create the payment network according to the currency and payment network type */
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
query GetNearConversionPayments(
2+
$reference: String!
3+
$to: String!
4+
$currency: String!
5+
$maxRateTimespan: Int!
6+
$contractAddress: String!
7+
) {
8+
payments(
9+
where: {
10+
reference: $reference
11+
to: $to
12+
currency: $currency
13+
maxRateTimespan_gte: $maxRateTimespan
14+
contractAddress: $contractAddress
15+
}
16+
orderBy: timestamp
17+
orderDirection: asc
18+
) {
19+
amount
20+
block
21+
receiptId
22+
feeAmount
23+
feeAddress
24+
from
25+
timestamp
26+
currency
27+
maxRateTimespan
28+
amountInCrypto
29+
feeAmountInCrypto
30+
}
31+
}

packages/payment-detection/src/thegraph/queries/near/GetPayments.graphql

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
query GetNearPayments($reference: String!, $to: String!) {
2-
payments(where: { reference: $reference, to: $to }, orderBy: timestamp, orderDirection: asc) {
1+
query GetNearPayments($reference: String!, $to: String!, $contractAddress: String!) {
2+
payments(
3+
where: { reference: $reference, to: $to, contractAddress: $contractAddress }
4+
orderBy: timestamp
5+
orderDirection: asc
6+
) {
37
amount
48
block
59
receiptId

0 commit comments

Comments
 (0)