-
Notifications
You must be signed in to change notification settings - Fork 92
feat: meta-pn #1405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: meta-pn #1405
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
cff4bbe
feat: meta-pn
leoslr 957a81b
feat: meta-pn
leoslr af03f65
revert change
leoslr c8f847a
revert change
leoslr 326c794
remove log
leoslr e440a3e
fixes
leoslr e2cf57f
fix meta validation
leoslr 5712089
fix types
leoslr a5231f2
feat: meta-pn payment processor
leoslr 6dae29f
clean
leoslr ed837d6
Merge branch 'master' into feat/meta-pn
leoslr 4a15e87
fix currency types
leoslr d94e7c3
integration tests
leoslr 06ff3ba
fix payment-detection tests
leoslr 10934ba
improve mock
leoslr 5542c70
fix comments and error messages
leoslr d465625
fix: small fixes
leoslr ee3520c
fix comments
leoslr 4050092
Merge branch 'master' into feat/meta-pn
MantisClone 3dcb548
update naming
leoslr 4b30684
Merge branch 'master' into feat/meta-pn
leoslr 6bcd9dc
additional utility method to compute payment references for meta pn
leoslr 77a3016
update comment
leoslr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,13 @@ | ||
| import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; | ||
| import { deepCopy } from '@requestnetwork/utils'; | ||
|
|
||
| export interface ICreationContext { | ||
| extensionsState: RequestLogicTypes.IExtensionStates; | ||
| extensionAction: ExtensionTypes.IAction; | ||
| requestState: RequestLogicTypes.IRequest; | ||
| actionSigner: IdentityTypes.IIdentity; | ||
| } | ||
|
|
||
| /** | ||
| * Abstract class to create extension | ||
| */ | ||
|
|
@@ -60,7 +67,12 @@ export abstract class AbstractExtension<TCreationParameters> implements Extensio | |
| throw Error(`This extension has already been created`); | ||
| } | ||
|
|
||
| copiedExtensionState[extensionAction.id] = this.applyCreation(extensionAction, timestamp); | ||
| copiedExtensionState[extensionAction.id] = this.applyCreation(extensionAction, timestamp, { | ||
| extensionsState, | ||
| extensionAction, | ||
| requestState, | ||
| actionSigner, | ||
| }); | ||
|
Comment on lines
+70
to
+75
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Necessary so we can call |
||
|
|
||
| return copiedExtensionState; | ||
| } | ||
|
|
@@ -99,6 +111,8 @@ export abstract class AbstractExtension<TCreationParameters> implements Extensio | |
| extensionAction: ExtensionTypes.IAction, | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| _timestamp: number, | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| context?: ICreationContext, | ||
| ): ExtensionTypes.IState { | ||
| if (!extensionAction.version) { | ||
| throw Error('version is required at creation'); | ||
|
|
||
239 changes: 239 additions & 0 deletions
239
packages/advanced-logic/src/extensions/payment-network/meta.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| import { | ||
| CurrencyTypes, | ||
| ExtensionTypes, | ||
| IdentityTypes, | ||
| RequestLogicTypes, | ||
| } from '@requestnetwork/types'; | ||
| import { ICreationContext } from '../abstract-extension'; | ||
| import AnyToErc20ProxyPaymentNetwork from './any-to-erc20-proxy'; | ||
| import AnyToEthProxyPaymentNetwork from './any-to-eth-proxy'; | ||
| import { deepCopy } from '@requestnetwork/utils'; | ||
| import DeclarativePaymentNetwork from './declarative'; | ||
|
|
||
| const CURRENT_VERSION = '0.1.0'; | ||
|
|
||
| export default class MetaPaymentNetwork< | ||
| TCreationParameters extends | ||
| ExtensionTypes.PnMeta.ICreationParameters = ExtensionTypes.PnMeta.ICreationParameters, | ||
| > extends DeclarativePaymentNetwork<TCreationParameters> { | ||
| public constructor( | ||
| protected currencyManager: CurrencyTypes.ICurrencyManager, | ||
| public extensionId: ExtensionTypes.PAYMENT_NETWORK_ID = ExtensionTypes.PAYMENT_NETWORK_ID.META, | ||
| public currentVersion: string = CURRENT_VERSION, | ||
| ) { | ||
| super(extensionId, currentVersion); | ||
| this.actions = { | ||
| ...this.actions, | ||
| [ExtensionTypes.PnMeta.ACTION.APPLY_ACTION_TO_PN]: | ||
| this.applyApplyActionToExtension.bind(this), | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Creates the extensionsData to create the meta extension payment detection | ||
| * | ||
| * @param creationParameters extensions parameters to create | ||
| * | ||
| * @returns IExtensionCreationAction the extensionsData to be stored in the request | ||
| */ | ||
| public createCreationAction( | ||
| creationParameters: TCreationParameters, | ||
| ): ExtensionTypes.IAction<TCreationParameters> { | ||
| Object.entries(creationParameters).forEach(([pnId, creationParameters]) => { | ||
| const pn = this.getExtension(pnId); | ||
| const subPnIdentifiers: string[] = []; | ||
|
|
||
| // Perform validation on sub-pn creation parameters | ||
| for (const param of creationParameters) { | ||
| pn.createCreationAction(param); | ||
| if (subPnIdentifiers.includes(param.salt)) { | ||
| throw new Error('Duplicate payment network identifier (salt)'); | ||
| } | ||
| subPnIdentifiers.push(param.salt); | ||
| } | ||
| }); | ||
|
|
||
| return super.createCreationAction(creationParameters); | ||
| } | ||
|
|
||
| /** | ||
| * Creates the extensionsData to perform an action on a sub-pn | ||
| * | ||
| * @param parameters parameters to create the action to perform | ||
| * | ||
| * @returns IAction the extensionsData to be stored in the request | ||
| */ | ||
| public createApplyActionToPn( | ||
| parameters: ExtensionTypes.PnMeta.IApplyActionToPn, | ||
| ): ExtensionTypes.IAction { | ||
| return { | ||
| action: ExtensionTypes.PnMeta.ACTION.APPLY_ACTION_TO_PN, | ||
| id: this.extensionId, | ||
| parameters: { | ||
| pnIdentifier: parameters.pnIdentifier, | ||
| action: parameters.action, | ||
| parameters: parameters.parameters, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Applies a creation extension action | ||
| * | ||
| * @param extensionAction action to apply | ||
| * @param timestamp action timestamp | ||
| * | ||
| * @returns state of the extension created | ||
| */ | ||
| protected applyCreation( | ||
| extensionAction: ExtensionTypes.IAction, | ||
| timestamp: number, | ||
| context?: ICreationContext, | ||
| ): ExtensionTypes.IState { | ||
| if (!context) { | ||
| throw new Error('Context is required'); | ||
| } | ||
| const values: Record<string, ExtensionTypes.IState> = {}; | ||
| Object.entries(extensionAction.parameters).forEach(([pnId, parameters]) => { | ||
| const pn = this.getExtension(pnId); | ||
|
|
||
| (parameters as any[]).forEach((params) => { | ||
| values[params.salt] = pn.applyActionToExtension( | ||
| {}, | ||
| { | ||
| action: 'create', | ||
| id: pnId as ExtensionTypes.PAYMENT_NETWORK_ID, | ||
| parameters: params, | ||
| version: pn.currentVersion, | ||
| }, | ||
| context.requestState, | ||
| context.actionSigner, | ||
| timestamp, | ||
| )[pnId]; | ||
| }); | ||
| }); | ||
|
|
||
| return { | ||
| ...super.applyCreation(extensionAction, timestamp), | ||
| events: [ | ||
| { | ||
| name: 'create', | ||
| parameters: { | ||
| ...extensionAction.parameters, | ||
| }, | ||
| timestamp, | ||
| }, | ||
| ], | ||
| values, | ||
MantisClone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }; | ||
| } | ||
|
|
||
| /** Applies an action on a sub-payment network | ||
| * | ||
| * @param extensionsState previous state of the extensions | ||
| * @param extensionAction action to apply | ||
| * @param requestState request state read-only | ||
| * @param actionSigner identity of the signer | ||
| * @param timestamp timestamp of the action | ||
| * | ||
| * @returns state of the extension created | ||
| */ | ||
| protected applyApplyActionToExtension( | ||
| extensionState: ExtensionTypes.IState, | ||
| extensionAction: ExtensionTypes.IAction, | ||
| requestState: RequestLogicTypes.IRequest, | ||
| actionSigner: IdentityTypes.IIdentity, | ||
| timestamp: number, | ||
| ): ExtensionTypes.IState { | ||
| const copiedExtensionState: ExtensionTypes.IState<any> = deepCopy(extensionState); | ||
| const { pnIdentifier, action, parameters } = extensionAction.parameters; | ||
| const extensionToActOn: ExtensionTypes.IState = copiedExtensionState.values[pnIdentifier]; | ||
|
|
||
| const pn = this.getExtension(extensionToActOn.id); | ||
|
|
||
| const subExtensionState = { | ||
| [extensionToActOn.id]: extensionToActOn, | ||
| }; | ||
|
|
||
| copiedExtensionState.values[pnIdentifier] = pn.applyActionToExtension( | ||
| subExtensionState, | ||
| { | ||
| id: extensionToActOn.id, | ||
| action, | ||
| parameters, | ||
| }, | ||
| requestState, | ||
| actionSigner, | ||
| timestamp, | ||
| )[extensionToActOn.id]; | ||
|
|
||
| // update events | ||
| copiedExtensionState.events.push({ | ||
| name: ExtensionTypes.PnMeta.ACTION.APPLY_ACTION_TO_PN, | ||
| parameters: { | ||
| pnIdentifier, | ||
| action, | ||
| parameters, | ||
| }, | ||
| timestamp, | ||
| from: actionSigner, | ||
| }); | ||
| return copiedExtensionState; | ||
| } | ||
|
|
||
| /** | ||
| * Validate the extension action regarding the currency and network | ||
| * It must throw in case of error | ||
| */ | ||
| protected validate( | ||
| request: RequestLogicTypes.IRequest, | ||
| extensionAction: ExtensionTypes.IAction, | ||
| ): void { | ||
| const pnIdentifiers: string[] = []; | ||
| if (extensionAction.action === ExtensionTypes.PnMeta.ACTION.CREATE) { | ||
| Object.entries(extensionAction.parameters).forEach(([pnId, parameters]: [string, any]) => { | ||
| // Checks that the PN is supported | ||
| this.getExtension(pnId); | ||
|
|
||
| if (parameters.action) { | ||
| throw new Error('Invalid action'); | ||
| } | ||
|
|
||
| for (const param of parameters) { | ||
| if (pnIdentifiers.includes(param.salt)) { | ||
| throw new Error('Duplicate payment network identifier'); | ||
| } | ||
| pnIdentifiers.push(param.salt); | ||
| } | ||
| }); | ||
| } else if (extensionAction.action === ExtensionTypes.PnMeta.ACTION.APPLY_ACTION_TO_PN) { | ||
| const { pnIdentifier } = extensionAction.parameters; | ||
|
|
||
| const subPnState: ExtensionTypes.IState = | ||
| request.extensions[ExtensionTypes.PAYMENT_NETWORK_ID.META]?.values?.[pnIdentifier]; | ||
| if (!subPnState) { | ||
| throw new Error(`No payment network with identifier ${pnIdentifier}`); | ||
| } | ||
|
|
||
| // Checks that the PN is supported | ||
| this.getExtension(subPnState.id); | ||
| } | ||
| } | ||
|
|
||
| private getExtension(pnId: string): ExtensionTypes.IExtension { | ||
| switch (pnId) { | ||
| case ExtensionTypes.PAYMENT_NETWORK_ID.ANY_DECLARATIVE: { | ||
| return new DeclarativePaymentNetwork(); | ||
| } | ||
| case ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_ERC20_PROXY: { | ||
| return new AnyToErc20ProxyPaymentNetwork(this.currencyManager); | ||
| } | ||
| case ExtensionTypes.PAYMENT_NETWORK_ID.ANY_TO_ETH_PROXY: { | ||
| return new AnyToEthProxyPaymentNetwork(this.currencyManager); | ||
| } | ||
| default: { | ||
| throw new Error(`Invalid PN: ${pnId}`); | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated but align with the method above.