-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Intergrate plan for payg * Change `orderType` to `projectType` * support payg in authHttpLink * Restructure for Apollo links * Add `responseLink` * Improve the import * Export more types * Resolve import in authLink test * Fix cluster auth link * feat: request token and report to chs * chore: reset * chore: skip test and TODO --------- Co-authored-by: mzxyz <[email protected]> Co-authored-by: HZHAIX <> Co-authored-by: cyrbuzz <[email protected]>
- Loading branch information
1 parent
0600381
commit faea387
Showing
19 changed files
with
326 additions
and
145 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains 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
File renamed without changes.
This file contains 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 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 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 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,119 @@ | ||
// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { ApolloLink, FetchResult, NextLink, Observable, Operation } from '@apollo/client/core'; | ||
import { Subscription } from 'zen-observable-ts'; | ||
|
||
import { isTokenExpired } from '../auth/authHelper'; | ||
import OrderMananger from '../utils/orderManager'; | ||
import { POST } from '../utils/query'; | ||
import { Logger } from '../utils/logger'; | ||
import { ChannelState, OrderType } from '../types'; | ||
|
||
export type AuthOptions = { | ||
authUrl: string; // the url for geting token | ||
projectId: string; // chainId or deploymentId for the project | ||
orderMananger: OrderMananger; // agreement manager for managing agreements | ||
logger: Logger; // logger for logging | ||
}; | ||
|
||
type RequestParams = { | ||
url: string; | ||
token: string; | ||
type: OrderType; | ||
}; | ||
|
||
export class ClusterAuthLink extends ApolloLink { | ||
private options: AuthOptions; | ||
private logger: Logger; | ||
private orderMananger: OrderMananger; | ||
|
||
constructor(options: AuthOptions) { | ||
super(); | ||
this.options = options; | ||
this.logger = options.logger; | ||
this.orderMananger = options.orderMananger; | ||
} | ||
|
||
override request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null { | ||
if (!forward) return null; | ||
|
||
return new Observable<FetchResult>((observer) => { | ||
let sub: Subscription; | ||
this.getRequestParams() | ||
.then((data) => { | ||
if (data) { | ||
const { token, url, type } = data; | ||
const headers = { authorization: `${token}` }; | ||
operation.setContext({ url, headers, type }); | ||
} | ||
|
||
sub = forward(operation).subscribe(observer); | ||
}) | ||
.catch((error) => { | ||
this.logger.warn(`Failed to get token: ${error.message}`); | ||
observer.error(new Error('failed to get indexer url and token')); | ||
}); | ||
|
||
return () => sub?.unsubscribe(); | ||
}); | ||
} | ||
|
||
private async getRequestParams(): Promise<RequestParams | undefined> { | ||
const orderType = await this.orderMananger.getNextOrderType(); | ||
if (!orderType) return undefined; | ||
switch (orderType) { | ||
case OrderType.agreement: | ||
return this.getAgreementRequestParams(); | ||
case OrderType.flexPlan: | ||
return this.getPlanRequestParams(); | ||
default: | ||
return undefined; | ||
} | ||
} | ||
|
||
private async getAgreementRequestParams(): Promise<RequestParams | undefined> { | ||
const nextAgreement = await this.orderMananger.getNextAgreement(); | ||
if (!nextAgreement) return undefined; | ||
|
||
const type = OrderType.agreement; | ||
const { token, id, url, indexer } = nextAgreement; | ||
if (!isTokenExpired(token)) return { token, url, type }; | ||
this.logger.debug(`request new token for indexer ${indexer}`); | ||
const { projectId, authUrl } = this.options; | ||
|
||
const tokenUrl = new URL('/orders/token', authUrl); | ||
const res = await POST<{ token: string }>(tokenUrl.toString(), { | ||
projectId, | ||
indexer, | ||
agreementId: id, | ||
}); | ||
|
||
this.orderMananger.updateTokenById(id, res.token); | ||
this.logger.debug(`request new token for indexer ${indexer} success`); | ||
return { token: `Bearer ${res.token}`, url, type }; | ||
} | ||
|
||
private async getPlanRequestParams(): Promise<RequestParams | undefined> { | ||
const nextPlan = await this.orderMananger.getNextPlan(); | ||
if (!nextPlan) return undefined; | ||
|
||
const type = OrderType.flexPlan; | ||
const { id: channelId, url, indexer } = nextPlan; | ||
|
||
this.logger.debug(`request new signature for indexer ${indexer}`); | ||
const { projectId: deployment, authUrl } = this.options; | ||
|
||
const tokenUrl = new URL('/channel/sign', authUrl); | ||
const signedState = await POST<ChannelState>(tokenUrl.toString(), { | ||
deployment, | ||
channelId, | ||
}); | ||
|
||
this.logger.debug(`state signature: ${signedState}`); | ||
const token = JSON.stringify(signedState); | ||
this.logger.debug(`request new state signature for indexer ${indexer} success`); | ||
|
||
return { token, url, type }; | ||
} | ||
} |
This file contains 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 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 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 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,10 @@ | ||
// Copyright 2020-2023 SubQuery Pte Ltd authors & contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
export * from './authLink'; | ||
export * from './clusterAuthLink'; | ||
export * from './dynamicHttpLink'; | ||
export * from './errorLink'; | ||
export * from './fallbackLink'; | ||
export * from './responseLink'; | ||
export * from './retryLink'; |
Oops, something went wrong.