@civic/gateway-client-core
Advanced tools
Comparing version 1.0.0-beta.8 to 1.0.0-beta.9
@@ -1,1 +0,1 @@ | ||
{"processes":{"154eaab3-2f27-4884-be0f-6fff37906244":{"parent":null,"children":[]},"262294de-2156-47fa-9c2a-fba4f81264f7":{"parent":null,"children":[]}},"files":{"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/defaults.ts":["154eaab3-2f27-4884-be0f-6fff37906244","262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/config.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/gatekeeperClient.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/url.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/index.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/local.logger.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/provider.logger.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/log.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/gatekeeperApi.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/chain.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/gatekeeperNetworkService.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/GatewayClientCore.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/orchestrate.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/listeners.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/civicPass.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/civicSign.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/fetch.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/gateway.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/inputs.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/remoteSign.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/issuance.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/orchestratorFlow.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/errors.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/expiry.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/refresh.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/userInteraction.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/userInteraction.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/partnerReview.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/common.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/state.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/stateMapping.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/flow.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/flow.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/gatewayStatus.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/error.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/initialisation.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/issuance.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/partnerReview.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/refresh.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/flowParameters.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/object.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/ui.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/ui.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/index.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/eventInterface.ts":["262294de-2156-47fa-9c2a-fba4f81264f7"]},"externalIds":{}} | ||
{"processes":{"4cd0b3f3-7831-4961-8af1-c99b2bace162":{"parent":null,"children":[]},"8f3826e1-7444-412e-8dae-753e6c893cc4":{"parent":null,"children":[]}},"files":{"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/defaults.ts":["4cd0b3f3-7831-4961-8af1-c99b2bace162","8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/config.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/gatekeeperClient.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/url.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/index.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/local.logger.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/logger/provider.logger.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/log.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/gatekeeperApi.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/chain.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/gatekeeperNetworkService.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/GatewayClientCore.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/orchestrate.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/listeners.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/civicPass.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/civicSign.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/fetch.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/gateway.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/inputs.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/remoteSign.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/issuance.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/orchestratorFlow.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/errors.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/expiry.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/refresh.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/userInteraction.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/userInteraction.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/partnerReview.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/common.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/state.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/stateMapping.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/flow.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/flow.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/gatewayStatus.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/error.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/initialisation.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/issuance.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/partnerReview.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/refresh.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/flowParameters.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/utils/object.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/state/ui.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/ui.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/index.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"],"/Users/kevincolgan/code/ociv-gatekeeper/packages/gateway-client-core/src/types/eventInterface.ts":["8f3826e1-7444-412e-8dae-753e6c893cc4"]},"externalIds":{}} |
@@ -30,2 +30,3 @@ import { GatekeeperAPIStatus, GatekeeperClientConfig, GatekeeperRecordResponse, RequestTokenIssuanceResponse, RequestTokenRefreshResponse, TokenRequest } from './types/gatekeeperApi'; | ||
refreshToken({ payload, proof, payer }: TokenRequest): Promise<RequestTokenRefreshResponse | null>; | ||
fetchFreshTransaction({ payer }: TokenRequest): Promise<RequestTokenRefreshResponse | null>; | ||
} |
@@ -6,2 +6,3 @@ import { GatekeeperClient } from './gatekeeperClient'; | ||
import { ChainClientInterface } from './types/chain'; | ||
import { CivicPassMessagePayload } from './types/civicPass'; | ||
import { GatewayCoreState } from './types/gatewayCore'; | ||
@@ -16,8 +17,13 @@ export declare class Issuance extends OrchestratorFlow { | ||
private timers; | ||
currentPayload: CivicPassMessagePayload; | ||
constructor(gatewayCoreStore: Store, chainImplementation: ChainClientInterface, gatekeeperClient: GatekeeperClient, abortController: AbortController, expectTokenTimeoutSeconds?: number); | ||
sendTransaction(): Promise<void>; | ||
setGatekeeperClientFlowId(): void; | ||
gatekeeperRequest(payer: string | undefined, fullState: GatewayCoreState): Promise<import("./types/gatekeeperApi").RequestTokenIssuanceResponse | null>; | ||
clearStateBeforeGatekeeperRequest(): void; | ||
makeGatekeeperRequest(payer: string | undefined): Promise<void>; | ||
freshTransactionGatekeeperRequest(payer: string | undefined): Promise<import("./types/gatekeeperApi").RequestTokenIssuanceResponse | null>; | ||
clearStateBeforeGatekeeperRequest(isFreshTransactionRequest?: boolean): void; | ||
makeGatekeeperRequest({ payer, isFreshTransactionRequest, }: { | ||
payer: string | undefined; | ||
isFreshTransactionRequest?: boolean; | ||
}): Promise<void>; | ||
retrieveFreshTransaction(payer: string | undefined): Promise<void>; | ||
statusHasValidToken(): boolean; | ||
@@ -24,0 +30,0 @@ expectOnChainToken(): void; |
@@ -6,7 +6,9 @@ import { GatewayCoreState, GatewayInput } from '../types/gatewayCore'; | ||
import { GatekeeperRecordResponse } from '../types/gatekeeperApi'; | ||
export declare const calculateIssuanceStartPreApprovedTransaction: (state: GatewayCoreState) => ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX | undefined; | ||
export declare const hasExistingDataCollectionProcessInProgress: (civicPassEvent: CivicPassMessageResponse | null) => boolean; | ||
export declare const isInPartnerReview: (gatekeeperRecord: GatewayInput<GatekeeperRecordResponse> | undefined) => boolean; | ||
export declare const preApprovedTxAvailable: (gatekeeperRecord: GatewayInput<GatekeeperRecordResponse> | undefined) => boolean; | ||
export type CalculateFromIssuanceAwaitingOnChainReturn = ExtendedGatewayStatus.CHAIN_TIMEOUT_ERROR; | ||
export declare const calculateFromIssuanceAwaitingOnChain: (state: GatewayCoreState) => CalculateFromIssuanceAwaitingOnChainReturn | undefined; | ||
export type CalculateFromIssuanceInReviewReturn = InternalGatewayStatus | ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW | ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION | ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN | ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR | ExtendedGatewayStatus.ISSUANCE_AWAITING_TRANSACTION_SEND | ExtendedGatewayStatus.ISSUANCE_AWAITING_THIRD_PARTY_TRANSACTION_SEND; | ||
export type CalculateFromIssuanceInReviewReturn = InternalGatewayStatus; | ||
export declare const calculateFromIssuanceInReview: (state: GatewayCoreState) => CalculateFromIssuanceInReviewReturn | undefined; | ||
@@ -24,4 +26,5 @@ export type CalculateFromGatekeeperIssuanceRequestedReturn = ExtendedGatewayStatus.ISSUANCE_CLIENT_PAYER_REQUESTED | GatewayStatus.IN_REVIEW; | ||
export declare const computeIssuanceInReview: (state: GatewayCoreState) => ComputeIssuanceInReviewType; | ||
export type CalculateIssuanceStatusReturn = ValidationGatewayStatusType | ExtendedGatewayStatus.RESTART | GatewayStatus.USER_INFORMATION_VALIDATED | GatewayStatus.COLLECTING_USER_INFORMATION | GatewayStatus.NOT_REQUESTED | ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW | ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION | ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN; | ||
export type CalculateIssuanceStatusReturn = ValidationGatewayStatusType | InternalGatewayStatus; | ||
export declare const calculateIssuanceStatus: (state: GatewayCoreState) => CalculateIssuanceStatusReturn | undefined; | ||
export declare const computeIssuanceStatus: (state: GatewayCoreState) => GatewayTokenCheckType | CalculateIssuanceStatusReturn; | ||
export declare const computeIssuanceStartPreApprovedTransaction: (state: GatewayCoreState) => GatewayTokenCheckType | ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; |
@@ -5,2 +5,3 @@ import { GatewayCoreState } from '../types/gatewayCore'; | ||
export type CalculateFromRefreshInReviewReturnType = ExtendedGatewayStatus.REFRESH_AWAITING_ON_CHAIN_TOKEN | ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR | ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND | ExtendedGatewayStatus.REFRESH_AWAITING_THIRD_PARTY_TRANSACTION_SEND; | ||
export declare const calculateRefreshStartPreApprovedTransaction: (state: GatewayCoreState) => ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX | undefined; | ||
export declare const calculateFromRefreshInReview: (state: GatewayCoreState) => CalculateFromRefreshInReviewReturnType | undefined; | ||
@@ -15,3 +16,3 @@ export type CalculateFromGatekeeperRefreshRequestedReturnType = ExtendedGatewayStatus.REFRESH_CLIENT_PAYER_REQUESTED | ExtendedGatewayStatus.REFRESH_IN_REVIEW; | ||
export declare const computeRefreshInReview: (state: GatewayCoreState) => ComputeRefreshInReviewReturnType; | ||
export type CalculateRefreshStatusReturnType = InternalGatewayStatus | ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED; | ||
export type CalculateRefreshStatusReturnType = InternalGatewayStatus; | ||
export declare const calculateRefreshStatus: (state: GatewayCoreState) => CalculateRefreshStatusReturnType | undefined; | ||
@@ -24,1 +25,2 @@ export type ComputeRefreshStatusReturnType = InternalGatewayStatus | ExtendedGatewayStatus.REFRESH_AWAITING_ON_CHAIN_TOKEN | ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR | ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND | ExtendedGatewayStatus.REFRESH_AWAITING_THIRD_PARTY_TRANSACTION_SEND | ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED; | ||
export declare const computeRefreshAwaitingOnChainToken: (state: GatewayCoreState) => ComputeRefreshAwaitingOnChainTokenReturnType; | ||
export declare const computeRefreshStartPreApprovedTransaction: (state: GatewayCoreState) => TokenNotRefreshRequiredReturnType | ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; |
@@ -25,3 +25,4 @@ export declare enum CivicPassMessageEventResult { | ||
SIGN_TRANSACTION = "signTransaction", | ||
AWAITING_TRANSACTION_CONFIRMATION = "awaitingTransactionConfirmation" | ||
AWAITING_TRANSACTION_CONFIRMATION = "awaitingTransactionConfirmation", | ||
START_PRE_APPROVED_TRANSACTION = "startPreApprovedTransaction" | ||
} | ||
@@ -28,0 +29,0 @@ export declare enum ValidationStatus { |
@@ -44,2 +44,3 @@ import { RequestInitRetryParams } from 'fetch-retry'; | ||
transaction?: string; | ||
preApprovedTxAvailable?: boolean; | ||
pending?: { | ||
@@ -46,0 +47,0 @@ presentationRequestId: string; |
@@ -33,2 +33,5 @@ export declare enum GatewayStatus { | ||
ISSUANCE_RESTART_DATA_COLLECTION = "ISSUANCE_RESTART_DATA_COLLECTION", | ||
ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX = "ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX", | ||
ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX = "ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX", | ||
ISSUANCE_CLIENT_SENDS_START_NEW_TX = "ISSUANCE_CLIENT_SENDS_START_NEW_TX", | ||
REFRESH_USER_INFORMATION_VALIDATED = "REFRESH_USER_INFORMATION_VALIDATED", | ||
@@ -40,4 +43,7 @@ REFRESH_CLIENT_PAYER_REQUESTED = "REFRESH_CLIENT_PAYER_REQUESTED", | ||
REFRESH_AWAITING_ON_CHAIN_TOKEN = "REFRESH_AWAITING_ON_CHAIN_TOKEN", | ||
RESTART_REFRESH = "RESTART_REFRESH" | ||
RESTART_REFRESH = "RESTART_REFRESH", | ||
REFRESH_CLIENT_SENDS_REQUEST_NEW_TX = "REFRESH_CLIENT_SENDS_REQUEST_NEW_TX", | ||
REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX = "REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX", | ||
REFRESH_CLIENT_SENDS_START_NEW_TX = "REFRESH_CLIENT_SENDS_START_NEW_TX" | ||
} | ||
export type InternalGatewayStatus = GatewayStatus | ExtendedGatewayStatus; |
@@ -36,2 +36,3 @@ import { ChainConfirmationTimeout, ChainError } from '../utils/errors'; | ||
referrer?: string; | ||
autoConfirmPowo?: boolean; | ||
}; | ||
@@ -38,0 +39,0 @@ export type ClientCoreOutput = { |
import { LogLevel } from './log'; | ||
export type Options = { | ||
autoShowModal: boolean; | ||
autoShowModal?: boolean; | ||
logLevel?: LogLevel; | ||
autoConfirmPowo?: boolean; | ||
clientSendsMaxRetries?: number; | ||
}; | ||
@@ -25,3 +27,2 @@ export interface WalletAdapter { | ||
expectTokenTimeoutSeconds?: number; | ||
clientSendMaxRetries?: number; | ||
disableInitialGatekeeperLookup?: boolean; | ||
@@ -28,0 +29,0 @@ gatekeeperConfig?: GatekeeperHttpConfig; |
@@ -5,3 +5,3 @@ module.exports = { | ||
'check-coverage': true, | ||
reporter: 'lcov', | ||
reporter: ['lcov', 'html'], | ||
all: true, | ||
@@ -8,0 +8,0 @@ lines: 97, |
{ | ||
"name": "@civic/gateway-client-core", | ||
"version": "1.0.0-beta.8", | ||
"version": "1.0.0-beta.9", | ||
"description": "Sample project for creating typescript library with support of iife and types.", | ||
@@ -15,3 +15,3 @@ "main": "dist/civic-gateway-client-core.min.js", | ||
"dev": "rollup -c -w", | ||
"test": "TS_NODE_PROJECT=./tsconfig.test.json nyc --reporter=text mocha --require mocha-steps --timeout 20000" | ||
"test": "TS_NODE_PROJECT=./tsconfig.test.json nyc mocha --require mocha-steps --timeout 20000" | ||
}, | ||
@@ -63,3 +63,3 @@ "keywords": [], | ||
"license": "MIT", | ||
"gitHead": "6f00f19ef98f89fc2ef0e8f3445d3b5cddaa3482" | ||
"gitHead": "57da35ab951fd1a31bd95629358962f02e6308a8" | ||
} |
@@ -18,2 +18,7 @@ - [Civic Gateway Client Core](#civic-gateway-client-core) | ||
- [UI Example](#ui-example) | ||
- [Error flow handling](#error-flow-handling) | ||
- [Civic-sign errors](#civic-sign-errors) | ||
- [Transaction send errors](#transaction-send-errors) | ||
- [In the 'issuanceClientSends-resume-requested' case:](#in-the-issuanceclientsends-resume-requested-case) | ||
- [In the 'retries-exhausted' case:](#in-the-retries-exhausted-case) | ||
@@ -165,1 +170,29 @@ # Civic Gateway Client Core | ||
``` | ||
## Error flow handling | ||
### Civic-sign errors | ||
If the user rejects a transaction, or the chainImplementation.proveWalletOwnership() function failes for any reason, the 'chainError' flow starts. Civic-sign errors are currently not retriable within the normal data-collection flow, as the iframe loses its context, so the gateway-client will choose to restart the flow using either `RESTART` or `RESTART_REFRESH`. | ||
### Transaction send errors | ||
#### In the 'issuanceClientSends-resume-requested' case: | ||
1. the gatekeeper tells the client that a transaction can be retried by including the flag `canRequestFreshTx: true` in the response | ||
2. the client changes state to `ISSUANCE_CLIENT_SENDS_START_NEW_TX` or REFRESH_CLIENT_SENDS_START_NEW_TX | ||
3. this change of status causes a new iframe screen to load: `startPreApprovedTransaction` | ||
4. the user is asked for POWO which successfully sent from the iframe in an issuance/success/payload civicpass event | ||
5. the `computeIssuanceStartPreApprovedTransaction` state fires and calculates a new status of `ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX` | ||
6. this causes the iframe to show the usual 'signTransaction' screen (with fees etc.) | ||
7. the orchestrator detects the `ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX` state and calls a new function on the issuance/refresh services `fetchFreshTransaction()` | ||
8. this calls the gatekeeperClient using a new client method `fetchFreshTransaction({ payer, payload })` which updates the gatekeeperRecord.received value in state | ||
9. the `computeIssuanceInReview()` state function fires and we're back in the normal 'client-sends' flow waiting to send the on-chain transaction | ||
#### In the 'retries-exhausted' case: | ||
1. the user goes through the normal client-sends flow until they get to the point where they have a transaction to sign/send | ||
2. the transaction sign/send fails (for whatever reason, either user cancels, not enough funds, or something goes wrong sending) | ||
3. the client reties with the same transaction until the 'clientSendsMaxRetries' limit is hit | ||
4. the client goes into `ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX` status | ||
5. this causes the iframe to show the usual 'signTransaction' screen (with fees etc.) | ||
7. the orchestrator detects the `ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX` state and calls a new function on the issuance/refresh services `fetchFreshTransaction()` | ||
8. this calls the gatekeeperClient using a new client method `fetchFreshTransaction({ payer, payload })` which updates the gatekeeperRecord.received value in state | ||
9. the `computeIssuanceInReview()` state function fires and we're back in the normal 'client-sends' flow waiting to send the on-chain transaction |
@@ -299,2 +299,43 @@ import { default as fetchBuilder } from 'fetch-retry'; | ||
} | ||
/** | ||
* Tries to fetch a new transaction for any flow | ||
* If it fails with a 5xx, handleFetchError will retry a number of times. | ||
*/ | ||
public async fetchFreshTransaction({ payer }: TokenRequest): Promise<RequestTokenRefreshResponse | null> { | ||
const url = new URL(`${this.baseUrl}/${this.initConfig.walletAddress}/transaction`); | ||
this.addQueryParams(url); | ||
logDebug( | ||
`fetchFreshTransaction: ${url.toString()}${this.queryParams?.gatekeeperNetworkAddress?.substring( | ||
0, | ||
6 | ||
)} this.abortController.signal.aborted: ${this.abortController.signal.aborted}` | ||
); | ||
const body = withoutUndefined({ | ||
payer, | ||
}); | ||
return this.fetchWithRetry(`${url.toString()}`, { | ||
method: 'POST', | ||
headers: { ...this.headers, 'Content-Type': 'application/json' }, | ||
body: JSON.stringify(body), | ||
signal: this.abortController.signal, | ||
}) | ||
.then(async (resp) => { | ||
const { status } = resp; | ||
const result = (await resp.json()) as unknown as RequestTokenRefreshResponse; | ||
return { | ||
...result, | ||
state: GatekeeperAPIStatus[GatekeeperAPIStatus[status] as keyof typeof GatekeeperAPIStatus], | ||
status, | ||
}; | ||
}) | ||
.catch((error) => { | ||
logError('fetchFreshTransaction', error); | ||
if (error.name === 'AbortError') { | ||
logDebug('error due to abort controller signal aborted'); | ||
return null; | ||
} | ||
throw error; | ||
}); | ||
} | ||
} |
@@ -7,2 +7,3 @@ import { GatekeeperClient } from './gatekeeperClient'; | ||
import { ChainClientInterface } from './types/chain'; | ||
import { CivicPassMessagePayload } from './types/civicPass'; | ||
import { InputStatus } from './types/fetch'; | ||
@@ -20,2 +21,4 @@ import { TokenRequest } from './types/gatekeeperApi'; | ||
currentPayload: CivicPassMessagePayload; | ||
constructor( | ||
@@ -92,11 +95,2 @@ readonly gatewayCoreStore: Store, | ||
setGatekeeperClientFlowId() { | ||
const fullState = this.gatewayCoreStore.getState(); | ||
if (!fullState.output?.flowParameters?.flowId) { | ||
this.log.error('Missing flowId', fullState); | ||
throw new Error('Missing flowId'); | ||
} | ||
this.gatekeeperClient.setFlowId(fullState.output?.flowParameters?.flowId); | ||
} | ||
async gatekeeperRequest(payer: string | undefined, fullState: GatewayCoreState) { | ||
@@ -107,2 +101,3 @@ if (!fullState.inputs.civicPass.received?.payload) { | ||
} | ||
this.currentPayload = fullState.inputs.civicPass.received?.payload; | ||
return this.gatekeeperClient.requestGatewayTokenFromGatekeeper({ | ||
@@ -114,3 +109,9 @@ payload: fullState.inputs.civicPass.received?.payload, | ||
clearStateBeforeGatekeeperRequest() { | ||
async freshTransactionGatekeeperRequest(payer: string | undefined) { | ||
return this.gatekeeperClient.fetchFreshTransaction({ | ||
payer, | ||
} as TokenRequest); | ||
} | ||
clearStateBeforeGatekeeperRequest(isFreshTransactionRequest = false) { | ||
this.gatewayCoreStore.setState((state) => { | ||
@@ -121,7 +122,43 @@ state.internal.errors.expectedOnChainToken = null; | ||
state.inputs.gatekeeperRecord.status = InputStatus.IN_PROGRESS; | ||
if (isFreshTransactionRequest) { | ||
state.internal.chainTransaction = undefined; | ||
} | ||
}); | ||
} | ||
async makeGatekeeperRequest(payer: string | undefined) { | ||
async makeGatekeeperRequest({ | ||
payer, | ||
isFreshTransactionRequest, | ||
}: { | ||
payer: string | undefined; | ||
isFreshTransactionRequest?: boolean; | ||
}) { | ||
const fullState = this.gatewayCoreStore.getState(); | ||
this.setGatekeeperClientFlowId(); | ||
this.log.debug('makeGatekeeperRequest', fullState); | ||
// clear any previous errors | ||
this.abortExpectedTokenTimer(); | ||
this.clearStateBeforeGatekeeperRequest(isFreshTransactionRequest); | ||
const requestPromise = isFreshTransactionRequest | ||
? this.freshTransactionGatekeeperRequest(payer) | ||
: this.gatekeeperRequest(payer, fullState); | ||
requestPromise | ||
.then((response) => { | ||
if (this.abortController.signal.aborted) return; | ||
this.gatewayCoreStore.setState((state) => { | ||
state.inputs.gatekeeperRecord.status = InputStatus.COMPLETE; | ||
state.inputs.gatekeeperRecord.received = response; | ||
}); | ||
}) | ||
.catch((error) => { | ||
this.gatewayCoreStore.setState((state) => { | ||
state.inputs.gatekeeperRecord.status = InputStatus.ERROR; | ||
state.inputs.gatekeeperRecord.error = error; | ||
}); | ||
}); | ||
} | ||
async retrieveFreshTransaction(payer: string | undefined) { | ||
const fullState = this.gatewayCoreStore.getState(); | ||
if (!fullState.inputs.civicPass.received?.payload) { | ||
@@ -132,3 +169,3 @@ this.log.error('Missing civicPass payload', fullState); | ||
this.setGatekeeperClientFlowId(); | ||
this.log.debug('makeGatekeeperRequest', fullState); | ||
this.log.debug('retrieveFreshTransaction', fullState); | ||
// clear any previous errors | ||
@@ -135,0 +172,0 @@ this.abortExpectedTokenTimer(); |
@@ -264,6 +264,14 @@ /** | ||
if (status === GatewayStatus.USER_INFORMATION_VALIDATED) { | ||
return this.issuance.makeGatekeeperRequest(this.payer); | ||
return this.issuance.makeGatekeeperRequest({ payer: this.payer }); | ||
} | ||
if ( | ||
[ | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
].includes(status as ExtendedGatewayStatus) | ||
) { | ||
return this.issuance.makeGatekeeperRequest({ payer: this.payer, isFreshTransactionRequest: true }); | ||
} | ||
if ( | ||
[ | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_TRANSACTION_SEND, | ||
@@ -279,4 +287,12 @@ ExtendedGatewayStatus.ISSUANCE_AWAITING_THIRD_PARTY_TRANSACTION_SEND, | ||
if (status === ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED) { | ||
return this.refresh.makeGatekeeperRequest(this.payer); | ||
return this.refresh.makeGatekeeperRequest({ payer: this.payer }); | ||
} | ||
if ( | ||
[ | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
].includes(status as ExtendedGatewayStatus) | ||
) { | ||
return this.refresh.makeGatekeeperRequest({ payer: this.payer, isFreshTransactionRequest: true }); | ||
} | ||
if (status === ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND) { | ||
@@ -288,2 +304,3 @@ return this.refresh.sendTransaction(); | ||
} | ||
if (status === ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW) { | ||
@@ -295,2 +312,4 @@ return this.partnerReview.pollForReviewFinished(); | ||
) { | ||
// Check if this does a record lookup. If it does a record lookupp, | ||
// The record lookup should update to the correct GT status | ||
return this.reset(); | ||
@@ -347,3 +366,2 @@ } | ||
const ownerDids = this.gatewayCoreStore.getState().internal.ownerDids; | ||
handleRemoteSignEvent(response, this.getRemoteSignInstance(), { | ||
@@ -355,4 +373,4 @@ chainImplementation: this.chainImplementation, | ||
.then((result) => { | ||
if (result) { | ||
this.log.error('No result from remote sign event'); | ||
if (!result) { | ||
this.log.warn('No result from remote sign event'); | ||
} | ||
@@ -359,0 +377,0 @@ this.gatewayCoreStore.setState((draft) => { |
import { GatekeeperClient } from './gatekeeperClient'; | ||
import { prefixLogger } from './logger'; | ||
import { LoggingInterface } from './logger/provider.logger'; | ||
@@ -12,3 +13,5 @@ import { Store } from './state/state'; | ||
readonly abortController: AbortController | ||
) {} | ||
) { | ||
this.log = prefixLogger('OrchestratorFlow'); | ||
} | ||
@@ -15,0 +18,0 @@ setGatekeeperClientFlowId() { |
@@ -35,2 +35,3 @@ import { GatekeeperClient } from './gatekeeperClient'; | ||
} | ||
this.currentPayload = fullState.inputs.civicPass.received?.payload; | ||
return this.gatekeeperClient.refreshToken({ | ||
@@ -37,0 +38,0 @@ payload: fullState.inputs.civicPass.received?.payload, |
@@ -6,2 +6,3 @@ import { DEFAULT_MAX_CLIENT_SENDS_RETRIES } from '../utils/defaults'; | ||
import { payerIsWalletOwner } from './common'; | ||
import { InputStatus } from '../types/fetch'; | ||
@@ -14,2 +15,9 @@ export const handleChainError = (state: GatewayCoreState): InternalGatewayStatus => { | ||
const isRefreshFlow = !!state.inputs.gatewayToken?.received; | ||
// handle the civic-sign error case separately: it currently requires a restart | ||
// as the iframe context is lost | ||
if (state.inputs.civicSign?.status === InputStatus.ERROR) { | ||
return isRefreshFlow ? ExtendedGatewayStatus.RESTART_REFRESH : ExtendedGatewayStatus.RESTART; | ||
} | ||
// handle the case where the user didn't send the client-sends transaction | ||
@@ -21,3 +29,3 @@ // TODO use a different civicPass action to differentiate between failed send transactions and failed signMessages | ||
(state.internal.chainTransaction.attempts || 0) <= | ||
(state.inputs.parameters?.clientSendMaxRetries || DEFAULT_MAX_CLIENT_SENDS_RETRIES) | ||
(state.inputs.parameters?.options?.clientSendsMaxRetries || DEFAULT_MAX_CLIENT_SENDS_RETRIES) | ||
) { | ||
@@ -34,4 +42,15 @@ if (isRefreshFlow) { | ||
} | ||
// handle a cancelled signMessage request | ||
return isRefreshFlow ? ExtendedGatewayStatus.RESTART_REFRESH : ExtendedGatewayStatus.RESTART; | ||
// The user tried to send the transaction, but it failed too many times | ||
// No need to restart the flow, instead we will request a new transaction | ||
if (isRefreshFlow) { | ||
return payerIsWalletOwner(state) | ||
? ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ||
: ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
return payerIsWalletOwner(state) | ||
? ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ||
: ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
@@ -38,0 +57,0 @@ return state.internal?.status as InternalGatewayStatus; |
@@ -55,2 +55,3 @@ import { FlowParameters, GatewayCoreState } from '../types/gatewayCore'; | ||
instanceId: state.internal.instanceId, | ||
autoConfirmPowo: state.inputs.parameters.options?.autoConfirmPowo, | ||
@@ -57,0 +58,0 @@ // from gatekeeper record response |
@@ -13,2 +13,3 @@ import { prefixLogger } from '../logger'; | ||
computeIssuanceRequested, | ||
computeIssuanceStartPreApprovedTransaction, | ||
computeIssuanceStatus, | ||
@@ -20,2 +21,3 @@ } from './issuance'; | ||
computeRefreshRequested, | ||
computeRefreshStartPreApprovedTransaction, | ||
computeRefreshStatus, | ||
@@ -63,2 +65,6 @@ } from './refresh'; | ||
ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
// ExtendedGatewayStatus.TOKEN_REFRESH_IN_REVIEW, // we don't support this flow yet | ||
@@ -162,3 +168,7 @@ ], | ||
[GatewayStatus.REFRESH_TOKEN_REQUIRED]: createTransition( | ||
[...gatewayTokenStatuses, ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED], | ||
[ | ||
...gatewayTokenStatuses, | ||
ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX, | ||
], | ||
computeRefreshStatus | ||
@@ -232,2 +242,6 @@ ), | ||
ExtendedGatewayStatus.RESTART_REFRESH, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
], | ||
@@ -244,2 +258,7 @@ handleChainError | ||
ExtendedGatewayStatus.REFRESH_AWAITING_ON_CHAIN_TOKEN, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND, | ||
], | ||
@@ -261,3 +280,10 @@ handleChainError | ||
[ExtendedGatewayStatus.CHAIN_SIGN_MESSAGE_ERROR]: createTransition( | ||
[ExtendedGatewayStatus.RESTART, ExtendedGatewayStatus.RESTART_REFRESH], | ||
[ | ||
ExtendedGatewayStatus.RESTART, | ||
ExtendedGatewayStatus.RESTART_REFRESH, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
], | ||
handleChainError | ||
@@ -299,2 +325,64 @@ ), | ||
), | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
], | ||
computeIssuanceStartPreApprovedTransaction | ||
), | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
...errorStatuses, | ||
ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_THIRD_PARTY_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN, // civic-sends case | ||
ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW, | ||
ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR, | ||
], | ||
computeIssuanceInReview | ||
), | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
...errorStatuses, | ||
ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_THIRD_PARTY_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN, // civic-sends case | ||
ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW, | ||
ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR, | ||
], | ||
computeIssuanceInReview | ||
), | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX, | ||
ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX, | ||
], | ||
computeRefreshStartPreApprovedTransaction | ||
), | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
...errorStatuses, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_THIRD_PARTY_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_ON_CHAIN_TOKEN, | ||
], | ||
computeRefreshInReview | ||
), | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX]: createTransition( | ||
[ | ||
...gatewayTokenStatuses, | ||
...errorStatuses, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_THIRD_PARTY_TRANSACTION_SEND, | ||
ExtendedGatewayStatus.REFRESH_AWAITING_ON_CHAIN_TOKEN, | ||
], | ||
computeRefreshInReview | ||
), | ||
}; | ||
@@ -301,0 +389,0 @@ |
@@ -24,2 +24,22 @@ import { GatewayCoreState, GatewayInput } from '../types/gatewayCore'; | ||
// we're waiting on a civic pass to provide us with a payload to send to the gatekeeper | ||
// when we get the issuance payload, then return ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ||
export const calculateIssuanceStartPreApprovedTransaction = ( | ||
state: GatewayCoreState | ||
): | ||
| ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ||
| ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX | ||
| undefined => { | ||
const civicPassEvent = state.inputs.civicPass?.received; | ||
if ( | ||
civicPassEvent?.action === CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION && | ||
civicPassEvent?.event === CivicPassMessageEventResult.SUCCESS && | ||
civicPassEvent?.payload !== undefined | ||
) { | ||
return payerIsWalletOwner(state) | ||
? ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ||
: ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
}; | ||
// Civic pass emits a data-collection status event for longer-running data-collection processes | ||
@@ -37,2 +57,9 @@ // to give more granular data-collection status updates | ||
}; | ||
export const preApprovedTxAvailable = ( | ||
gatekeeperRecord: GatewayInput<GatekeeperRecordResponse> | undefined | ||
): boolean => { | ||
return !!gatekeeperRecord?.received?.payload?.preApprovedTxAvailable; | ||
}; | ||
export type CalculateFromIssuanceAwaitingOnChainReturn = ExtendedGatewayStatus.CHAIN_TIMEOUT_ERROR; | ||
@@ -50,10 +77,4 @@ export const calculateFromIssuanceAwaitingOnChain = ( | ||
export type CalculateFromIssuanceInReviewReturn = | ||
| InternalGatewayStatus | ||
| ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW | ||
| ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION | ||
| ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN | ||
| ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR | ||
| ExtendedGatewayStatus.ISSUANCE_AWAITING_TRANSACTION_SEND | ||
| ExtendedGatewayStatus.ISSUANCE_AWAITING_THIRD_PARTY_TRANSACTION_SEND; | ||
export type CalculateFromIssuanceInReviewReturn = InternalGatewayStatus; | ||
export const calculateFromIssuanceInReview = ( | ||
@@ -193,11 +214,4 @@ state: GatewayCoreState | ||
export type CalculateIssuanceStatusReturn = | ||
| ValidationGatewayStatusType | ||
| ExtendedGatewayStatus.RESTART | ||
| GatewayStatus.USER_INFORMATION_VALIDATED | ||
| GatewayStatus.COLLECTING_USER_INFORMATION | ||
| GatewayStatus.NOT_REQUESTED | ||
| ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW | ||
| ExtendedGatewayStatus.ISSUANCE_RESTART_DATA_COLLECTION | ||
| ExtendedGatewayStatus.ISSUANCE_AWAITING_ON_CHAIN_TOKEN; | ||
export type CalculateIssuanceStatusReturn = ValidationGatewayStatusType | InternalGatewayStatus; | ||
export const calculateIssuanceStatus = (state: GatewayCoreState): CalculateIssuanceStatusReturn | undefined => { | ||
@@ -230,2 +244,3 @@ const civicPassEvent = state.inputs.civicPass?.received; | ||
} | ||
return GatewayStatus.NOT_REQUESTED; | ||
@@ -236,2 +251,9 @@ } | ||
if (gatekeeperRecord?.received?.state === GatekeeperAPIStatus.REQUESTED) { | ||
if (preApprovedTxAvailable(gatekeeperRecord)) { | ||
if (payerIsWalletOwner(state)) { | ||
return ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX; | ||
} | ||
return ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
if (isInPartnerReview(gatekeeperRecord)) { | ||
@@ -264,1 +286,11 @@ return ExtendedGatewayStatus.TOKEN_IN_PARTNER_REVIEW; | ||
(state.internal?.status as GatewayTokenCheckType | CalculateIssuanceStatusReturn); | ||
export const computeIssuanceStartPreApprovedTransaction = ( | ||
state: GatewayCoreState | ||
): | ||
| GatewayTokenCheckType | ||
| ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX | ||
| ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX => | ||
statusFromGatewayTokenIfExists(state) || | ||
calculateIssuanceStartPreApprovedTransaction(state) || | ||
(state.internal?.status as GatewayTokenCheckType | ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX); |
@@ -14,2 +14,3 @@ import { GatewayCoreState } from '../types/gatewayCore'; | ||
import { ChainConfirmationTimeout, ErrorCode } from '../utils/errors'; | ||
import { preApprovedTxAvailable } from './issuance'; | ||
@@ -22,2 +23,22 @@ export type CalculateFromRefreshInReviewReturnType = | ||
// we're waiting on a civic pass to provide us with a payload to send to the gatekeeper | ||
// when we get the refresh payload, then return REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ||
export const calculateRefreshStartPreApprovedTransaction = ( | ||
state: GatewayCoreState | ||
): | ||
| ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ||
| ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX | ||
| undefined => { | ||
const civicPassEvent = state.inputs.civicPass?.received; | ||
if ( | ||
civicPassEvent?.action === CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION && | ||
civicPassEvent?.event === CivicPassMessageEventResult.SUCCESS && | ||
civicPassEvent?.payload !== undefined | ||
) { | ||
return payerIsWalletOwner(state) | ||
? ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ||
: ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
}; | ||
export const calculateFromRefreshInReview = ( | ||
@@ -102,8 +123,12 @@ state: GatewayCoreState | ||
export type CalculateRefreshStatusReturnType = | ||
| InternalGatewayStatus | ||
| ExtendedGatewayStatus.REFRESH_USER_INFORMATION_VALIDATED; | ||
export type CalculateRefreshStatusReturnType = InternalGatewayStatus; | ||
export const calculateRefreshStatus = (state: GatewayCoreState): CalculateRefreshStatusReturnType | undefined => { | ||
const civicPassEvent = state.inputs.civicPass?.received; | ||
if (preApprovedTxAvailable(state.inputs.gatekeeperRecord)) { | ||
if (payerIsWalletOwner(state)) { | ||
return ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX; | ||
} | ||
return ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX; | ||
} | ||
if ( | ||
@@ -158,1 +183,13 @@ civicPassEvent?.action === CivicPassMessageAction.REFRESH && | ||
(state.internal?.status as InternalGatewayStatus); | ||
export const computeRefreshStartPreApprovedTransaction = ( | ||
state: GatewayCoreState | ||
): | ||
| TokenNotRefreshRequiredReturnType | ||
| ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX | ||
| ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX => | ||
tokenNotRefreshRequired(state) || | ||
calculateRefreshStartPreApprovedTransaction(state) || | ||
(state.internal?.status as | ||
| TokenNotRefreshRequiredReturnType | ||
| ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX); |
@@ -41,2 +41,9 @@ import { CivicPassMessageAction } from '../types/civicPass'; | ||
[ExtendedGatewayStatus.REFRESH_AWAITING_THIRD_PARTY_TRANSACTION_SEND]: CivicPassMessageAction.TOKEN_REFRESH_IN_REVIEW, | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX]: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION, | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX]: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION, | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX]: CivicPassMessageAction.SIGN_TRANSACTION, | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX]: CivicPassMessageAction.SIGN_TRANSACTION, | ||
[ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX]: CivicPassMessageAction.TOKEN_IN_REVIEW, | ||
[ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX]: | ||
CivicPassMessageAction.TOKEN_REFRESH_IN_REVIEW, | ||
}; | ||
@@ -88,2 +95,14 @@ | ||
return GatewayStatus.IN_REVIEW; | ||
case ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX: | ||
return GatewayStatus.USER_INFORMATION_VALIDATED; | ||
case ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX: | ||
return GatewayStatus.USER_INFORMATION_VALIDATED; | ||
case ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX: | ||
return GatewayStatus.IN_REVIEW; | ||
case ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX: | ||
return GatewayStatus.IN_REVIEW; | ||
case ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX: | ||
return GatewayStatus.IN_REVIEW; | ||
case ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX: | ||
return GatewayStatus.IN_REVIEW; | ||
default: | ||
@@ -90,0 +109,0 @@ // otherwise return GatewayStatus |
@@ -27,2 +27,3 @@ export enum CivicPassMessageEventResult { | ||
AWAITING_TRANSACTION_CONFIRMATION = 'awaitingTransactionConfirmation', | ||
START_PRE_APPROVED_TRANSACTION = 'startPreApprovedTransaction', | ||
} | ||
@@ -29,0 +30,0 @@ |
@@ -46,5 +46,7 @@ import { RequestInitRetryParams } from 'fetch-retry'; | ||
}; | ||
export type GatekeeperRecordResponse = GatekeeperErrorResponse & { | ||
state: GatekeeperAPIStatus; | ||
transaction?: string; | ||
preApprovedTxAvailable?: boolean; | ||
pending?: { presentationRequestId: string }; | ||
@@ -51,0 +53,0 @@ }; |
@@ -35,2 +35,5 @@ export enum GatewayStatus { | ||
ISSUANCE_RESTART_DATA_COLLECTION = 'ISSUANCE_RESTART_DATA_COLLECTION', // the user already requested a token but it didn't complete successfully | ||
ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX = 'ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX', | ||
ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX = 'ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX', // triggers a request to the gatekeeper for a new transaction | ||
ISSUANCE_CLIENT_SENDS_START_NEW_TX = 'ISSUANCE_CLIENT_SENDS_START_NEW_TX', // We need to ask the user to request a new transaction | ||
@@ -44,2 +47,5 @@ REFRESH_USER_INFORMATION_VALIDATED = 'REFRESH_USER_INFORMATION_VALIDATED', | ||
RESTART_REFRESH = 'RESTART_REFRESH', // the user needs to restart the flow | ||
REFRESH_CLIENT_SENDS_REQUEST_NEW_TX = 'REFRESH_CLIENT_SENDS_REQUEST_NEW_TX', // triggers a request to the gatekeeper for a new transaction | ||
REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX = 'REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX', // triggers a request to the gatekeeper for a new transaction | ||
REFRESH_CLIENT_SENDS_START_NEW_TX = 'REFRESH_CLIENT_SENDS_START_NEW_TX', // We need to ask the user to request a new transaction | ||
} | ||
@@ -46,0 +52,0 @@ |
@@ -39,2 +39,3 @@ import { ChainConfirmationTimeout, ChainError } from '../utils/errors'; | ||
referrer?: string; | ||
autoConfirmPowo?: boolean; | ||
}; | ||
@@ -41,0 +42,0 @@ |
import { LogLevel } from './log'; | ||
export type Options = { | ||
autoShowModal: boolean; | ||
autoShowModal?: boolean; | ||
logLevel?: LogLevel; | ||
autoConfirmPowo?: boolean; | ||
clientSendsMaxRetries?: number; | ||
}; | ||
@@ -29,3 +31,2 @@ | ||
expectTokenTimeoutSeconds?: number; // the time in milliseconds to wait for a token to go active before timing out | ||
clientSendMaxRetries?: number; // the number of times a client can attempt to send a transaction before the flow is restarted | ||
disableInitialGatekeeperLookup?: boolean; // when set to true, the client will not call the GK-API on load | ||
@@ -32,0 +33,0 @@ gatekeeperConfig?: GatekeeperHttpConfig; |
@@ -25,6 +25,8 @@ import { step } from 'mocha-steps'; | ||
testHelpers = new IntegrationTestHelpers(sandbox); | ||
testHelpers.stubSuccessfulFetchCalls({ | ||
getResponsePayload: [GatekeeperAPIStatus.REQUESTED, { provider: 'web' }], | ||
payer: '0x123', | ||
testHelpers.stubSuccessfulFetchCalls(); | ||
// override the gatekeeper GET response to indicate a requested token, allowing a fresh TX to be requested | ||
testHelpers.stubGetFetchCall({ | ||
getResponsePayload: [GatekeeperAPIStatus.REQUESTED, { preApprovedTxAvailable: true }], | ||
}); | ||
testHelpers.stubFreshTransactionPostFetchCall(); | ||
}); | ||
@@ -47,4 +49,5 @@ | ||
step('2. Expect gateway status to change to NOT_REQUESTED', async () => { | ||
testHelpers.expectNotRequested(); | ||
step('2. Expect gateway status to change to start new-transaction flow', async () => { | ||
await sleep(110); | ||
testHelpers.expectStartNewTx(); | ||
}); | ||
@@ -56,3 +59,3 @@ | ||
step('4. Simulate a successfull client sending of transaction when presented to the user', async () => { | ||
step('4. Prepare a successfull client sending of transaction when presented to the user', async () => { | ||
testHelpers.prepareSuccessfulHandleTransaction(); | ||
@@ -62,6 +65,11 @@ }); | ||
step('5. Emit a civic-pass event to initiate the GK-API issuance request', async () => { | ||
await testHelpers.simulateSucessfulDataCollectionTriggeringGKTokenRequest(); | ||
await testHelpers.simulateIframeEventTriggeringFreshTransactionRequest(); | ||
}); | ||
step('6. Wait for the transaction to be returned and sent by the client', async () => { | ||
step('6. The user should be presented with a screen to re-fetch the transaction', async () => { | ||
await sleep(120); | ||
testHelpers.expectClientSendsRequestNewTransaction(); | ||
}); | ||
step('7. Wait for the transaction to be returned and sent by the client', async () => { | ||
await sleep(200); | ||
@@ -72,3 +80,3 @@ await testHelpers.expectClientSendTransactionToBeSent(); | ||
step( | ||
'7. OnChain listener fires with active token and gateway status and gateway token are updated to active', | ||
'8. OnChain listener fires with active token and gateway status and gateway token are updated to active', | ||
async () => { | ||
@@ -75,0 +83,0 @@ await testHelpers.simulateActiveOnChainToken(); |
@@ -15,98 +15,17 @@ import { step } from 'mocha-steps'; | ||
describe('GatewayClientCore issuance client sends integration tests', () => { | ||
describe('GatewayClientCore issuance client sends with retries integration tests', () => { | ||
let testHelpers: IntegrationTestHelpers; | ||
before(() => { | ||
testHelpers = new IntegrationTestHelpers(sandbox); | ||
testHelpers.stubSuccessfulFetchCalls(); | ||
}); | ||
context('with all the attempts failing', () => { | ||
before(() => { | ||
testHelpers = new IntegrationTestHelpers(sandbox); | ||
testHelpers.stubSuccessfulFetchCalls(); | ||
}); | ||
after(() => { | ||
testHelpers.cleanup(); | ||
sandbox.restore(); | ||
}); | ||
step('1. expect the Gatekeeper client to successfully initialize with clientSendMaxRetries of 2', () => { | ||
testHelpers.initializeGatewayCore({ clientSendMaxRetries: 2 }); | ||
}); | ||
step('wait for GK and on-chain checks to complete', async () => { | ||
await sleep(110); | ||
}); | ||
step('2. Expect gateway status to change to NOT_REQUESTED', async () => { | ||
testHelpers.expectNotRequested(); | ||
}); | ||
step('3. Expect successful civic-sign public-key, did and POWO flows', async () => { | ||
await testHelpers.expectSuccessfulCivicSignProofFlow(); | ||
}); | ||
step('4. Set up tests so that user will abort transaction', () => { | ||
testHelpers.prepareUserAbortedTransaction(); | ||
}); | ||
step('5. Simulate initial client sending data to gatekeeper then aborting transaction', async () => { | ||
await testHelpers.simulateSucessfulDataCollectionTriggeringGKTokenRequest(); | ||
}); | ||
step('6. Wait for chain transaction to attempt to send and fail', async () => { | ||
await sleep(120); | ||
}); | ||
step('7. The status should change to ERROR when the transaction gets aborted', async () => { | ||
testHelpers.expectChainError(); | ||
}); | ||
step('8. Simulate client retrying once the chain error screen is shown', async () => { | ||
await testHelpers.simulateCivicPassChainFailureEvent(); | ||
}); | ||
step('9. Wait for chain transaction to attempt to send and fail', async () => { | ||
await sleep(120); | ||
}); | ||
step('10. The status should change to ERROR', async () => { | ||
testHelpers.expectChainError(); | ||
}); | ||
step('11. Simulate another error client sending the transaction', async () => { | ||
await testHelpers.simulateCivicPassChainFailureEvent(); | ||
}); | ||
step('12. Wait for chain transaction to attempt to send and fail', async () => { | ||
await sleep(120); | ||
}); | ||
step('13. The status should change to ERROR', async () => { | ||
testHelpers.expectChainError(); | ||
}); | ||
step('14. Simulate another error client sending the transaction', async () => { | ||
await testHelpers.simulateCivicPassChainFailureEvent(); | ||
}); | ||
step('15. Wait for flow to restart', async () => { | ||
await sleep(100); | ||
}); | ||
step('15. Expect to restart flow in NOT_REQUESTED', async () => { | ||
testHelpers.expectNotRequested(); | ||
}); | ||
after(() => { | ||
testHelpers.cleanup(); | ||
sandbox.restore(); | ||
}); | ||
context('with the last attempt succeeding', () => { | ||
before(() => { | ||
testHelpers = new IntegrationTestHelpers(sandbox); | ||
testHelpers.stubSuccessfulFetchCalls(); | ||
}); | ||
after(() => { | ||
testHelpers.cleanup(); | ||
sandbox.restore(); | ||
}); | ||
context('send on-chain TX with the last attempt succeeding', () => { | ||
step('1. expect the Gatekeeper client to successfully initialize with clientSendMaxRetries of 2', () => { | ||
testHelpers.initializeGatewayCore({ clientSendMaxRetries: 2 }); | ||
testHelpers.initializeGatewayCore({ options: { clientSendsMaxRetries: 2 } }); | ||
}); | ||
@@ -113,0 +32,0 @@ |
@@ -22,2 +22,3 @@ import { step } from 'mocha-steps'; | ||
testHelpers.stubSuccessfulFetchCalls({ withExistingGatekeeperRecord: true }); | ||
testHelpers.stubRefreshPatchCall(); | ||
// stub find token with an expired token | ||
@@ -61,9 +62,14 @@ testHelpers.stubFindToken({ | ||
step('6. Wait for the GK refresh request to complete', async () => { | ||
await sleep(120); | ||
await sleep(100); | ||
}); | ||
step('7. expect state to be IN_REVIEW', () => { | ||
step('7. expect state to be IN_REVIEW awaiting client-sends', () => { | ||
testHelpers.expectClientSendsInReview(); | ||
}); | ||
step('7. expect state to be IN_REVIEW awaitng on-chain confirmation', async () => { | ||
await sleep(20); | ||
testHelpers.expectClientSendsAwaitingConfirmation(); | ||
}); | ||
step( | ||
@@ -70,0 +76,0 @@ '8 OnChain listener fires with active token and gateway status and gateway token are updated to active', |
@@ -5,3 +5,3 @@ import sinon from 'sinon'; | ||
import { createGatewayCoreStore, Store } from '../src/state/state'; | ||
import { GatekeeperAPIStatus, GatekeeperClientConfig } from '../src/types/gatekeeperApi'; | ||
import { GatekeeperAPIStatus, GatekeeperClientConfig, RequestTokenIssuanceResponse } from '../src/types/gatekeeperApi'; | ||
import { GatekeeperClient } from '../src/gatekeeperClient'; | ||
@@ -246,3 +246,3 @@ import { ChainClientInterface, ChainType, GatewayCoreState } from '../src'; | ||
context('makeGatekeeperRequest', () => { | ||
context('with no received payload', () => { | ||
context('with no flowId', () => { | ||
it('should throw an error', async () => { | ||
@@ -257,3 +257,3 @@ getStateStub.returns({ | ||
issuance = new Issuance(gatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
return expect(issuance.makeGatekeeperRequest('payer')).to.be.rejectedWith('Missing civicPass payload'); | ||
return expect(issuance.makeGatekeeperRequest({ payer: 'payer' })).to.be.rejectedWith('Missing flowId'); | ||
}); | ||
@@ -281,3 +281,3 @@ }); | ||
issuance = new Issuance(realGatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
issuance.makeGatekeeperRequest('payer'); | ||
issuance.makeGatekeeperRequest({ payer: 'payer' }); | ||
await sleep(100); | ||
@@ -290,3 +290,111 @@ const fullState = realGatewayCoreStore.getState(); | ||
}); | ||
context('freshTransactionGatekeeperRequest', () => { | ||
it('should call gatekeeper client fetchFreshTransaction', async () => { | ||
const fetchFreshTransactionStub = sandbox | ||
.stub(GatekeeperClient.prototype, 'fetchFreshTransaction') | ||
.resolves({ status: GatekeeperAPIStatus.REQUESTED } as RequestTokenIssuanceResponse); | ||
issuance = new Issuance(gatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
issuance.freshTransactionGatekeeperRequest('payer'); | ||
expect(fetchFreshTransactionStub).calledWith({ payer: 'payer' }); | ||
}); | ||
}); | ||
}); | ||
context('retrieveFreshTransaction', () => { | ||
beforeEach(() => { | ||
const testHelpers = new IntegrationTestHelpers(sandbox, { clientSends: false }); | ||
realGatewayCoreStore = testHelpers.getInitializedStore(); | ||
realGatewayCoreStore.setState((draft) => { | ||
draft.inputs.civicPass = { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
action: CivicPassMessageAction.ISSUANCE, | ||
payload: { status: ValidationStatus.COMPLETED }, | ||
}, | ||
}; | ||
}); | ||
}); | ||
it('should throw an error if there is no civicPass payload', async () => { | ||
issuance = new Issuance(gatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
received: undefined, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
getStateStub.returns(state); | ||
return expect(issuance.retrieveFreshTransaction('payer')).to.be.rejectedWith('Missing civicPass payload'); | ||
}); | ||
it('should call gatekeeperRequest with the correct parameters', async () => { | ||
issuance = new Issuance(realGatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
sandbox.stub(issuance, 'gatekeeperRequest').resolves({ state: GatekeeperAPIStatus.ISSUED, status: 200 }); | ||
await issuance.retrieveFreshTransaction('payer'); | ||
expect(issuance.gatekeeperRequest).to.have.been.calledOnceWith('payer'); | ||
}); | ||
it('should set the state correctly on successful request', async () => { | ||
issuance = new Issuance(realGatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
sandbox.stub(issuance, 'gatekeeperRequest').resolves({ state: GatekeeperAPIStatus.ISSUED, status: 200 }); | ||
await issuance.retrieveFreshTransaction('payer'); | ||
const fullState = realGatewayCoreStore.getState(); | ||
expect(fullState.inputs.gatekeeperRecord.status).to.eq(InputStatus.COMPLETE); | ||
expect(fullState.inputs.gatekeeperRecord.received).to.deep.eq({ state: GatekeeperAPIStatus.ISSUED, status: 200 }); | ||
}); | ||
it('should set the error state correctly on failed request', async () => { | ||
issuance = new Issuance(realGatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
sandbox.stub(issuance, 'gatekeeperRequest').rejects(new Error('test_error')); | ||
await issuance.retrieveFreshTransaction('payer'); | ||
await sleep(100); | ||
const fullState = realGatewayCoreStore.getState(); | ||
expect(fullState.inputs.gatekeeperRecord.status).to.eq(InputStatus.ERROR); | ||
expect((fullState.inputs.gatekeeperRecord.error as Error).message).to.eq('test_error'); | ||
}); | ||
}); | ||
context('restartDataCollection', () => { | ||
beforeEach(() => { | ||
const testHelpers = new IntegrationTestHelpers(sandbox, { clientSends: false }); | ||
realGatewayCoreStore = testHelpers.getInitializedStore(); | ||
realGatewayCoreStore.setState((draft) => { | ||
draft.inputs.civicPass = { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
action: CivicPassMessageAction.ISSUANCE, | ||
payload: { status: ValidationStatus.COMPLETED }, | ||
}, | ||
}; | ||
}); | ||
}); | ||
it('should reset civicPass received data to null', () => { | ||
issuance = new Issuance(realGatewayCoreStore, chainImplementation, gatekeeperClient, abortController); | ||
const initialState = { | ||
inputs: { | ||
civicPass: { | ||
received: { | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
action: CivicPassMessageAction.ISSUANCE, | ||
payload: { status: ValidationStatus.COMPLETED }, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
realGatewayCoreStore.setState((draft) => { | ||
draft.inputs.civicPass = initialState.inputs.civicPass; | ||
}); | ||
issuance.restartDataCollection(); | ||
const updatedState = realGatewayCoreStore.getState(); | ||
expect(updatedState.inputs.civicPass.received).to.be.null; | ||
}); | ||
}); | ||
}); |
@@ -103,4 +103,29 @@ import { ClientCoreInternal, ExtendedGatewayStatus, GatewayCoreState, GatewayStatus } from '../../src'; | ||
const result = handleChainError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART_REFRESH); | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should return RESTART_REFRESH', () => { | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.FAILURE, | ||
action: CivicPassMessageAction.CHAIN_ERROR, | ||
}, | ||
}, | ||
parameters: { | ||
payer: 'test-payer', | ||
}, | ||
gatekeeperRecord: { status: null, received: null }, | ||
gatewayToken: { status: null, received: { state: 'ACTIVE' } }, | ||
}, | ||
internal: internalState, | ||
output: {}, | ||
} as unknown as GatewayCoreState; | ||
const result = handleChainError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
@@ -126,5 +151,30 @@ | ||
const result = handleChainError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should return RESTART', () => { | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.FAILURE, | ||
action: CivicPassMessageAction.CHAIN_ERROR, | ||
}, | ||
}, | ||
gatekeeperRecord: { status: null, received: null }, | ||
gatewayToken: { status: null, received: null }, | ||
parameters: { | ||
payer: 'test-payer', | ||
}, | ||
}, | ||
internal: internalState, | ||
output: {}, | ||
} as unknown as GatewayCoreState; | ||
const result = handleChainError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
@@ -167,2 +217,54 @@ }); | ||
}); | ||
context('with a civic sign failure', () => { | ||
context('with a gateway token', () => { | ||
it('should return RESTART_REFRESH', () => { | ||
const state = { | ||
inputs: { | ||
civicSign: { | ||
status: InputStatus.ERROR, | ||
}, | ||
civicPass: { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.FAILURE, | ||
action: CivicPassMessageAction.ERROR, | ||
}, | ||
}, | ||
gatekeeperRecord: { status: null, received: null }, | ||
gatewayToken: { status: null, received: { state: 'ACTIVE' } }, | ||
}, | ||
internal: internalState, | ||
output: {}, | ||
} as unknown as GatewayCoreState; | ||
const result = handleGatekeeperError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART_REFRESH); | ||
}); | ||
}); | ||
context('with no gateway token', () => { | ||
it('should return RESTART', () => { | ||
const state = { | ||
inputs: { | ||
civicSign: { | ||
status: InputStatus.ERROR, | ||
}, | ||
civicPass: { | ||
status: InputStatus.COMPLETE, | ||
received: { | ||
event: CivicPassMessageEventResult.FAILURE, | ||
action: CivicPassMessageAction.ERROR, | ||
}, | ||
}, | ||
gatekeeperRecord: { status: null, received: null }, | ||
gatewayToken: { status: null, received: null }, | ||
}, | ||
internal: internalState, | ||
output: {}, | ||
} as unknown as GatewayCoreState; | ||
const result = handleGatekeeperError(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -169,0 +271,0 @@ |
@@ -225,8 +225,30 @@ import { InputStatus } from '../../src/types/fetch'; | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should set status to RESTART', () => { | ||
const state = { | ||
inputs: { | ||
...initialInputState, | ||
civicPass: { | ||
received: { event: CivicPassMessageEventResult.FAILURE, action: CivicPassMessageAction.CHAIN_ERROR }, | ||
}, | ||
parameters: { | ||
payer: 'test-payer', | ||
}, | ||
}, | ||
internal: { | ||
chainTransaction: { error: new ChainError('error sending tx'), attempts: 4 }, | ||
status: ExtendedGatewayStatus.CHAIN_TRANSACTION_ERROR, | ||
}, | ||
} as GatewayCoreState; | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
context('with internal status as CHAIN_SIGN_MESSAGE_ERROR', () => { | ||
it('should set status to RESTART if it is not refreh flow', () => { | ||
it('should set status to RESTART if it is not refresh flow', () => { | ||
const state = { | ||
@@ -247,5 +269,29 @@ inputs: { | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should set status to RESTART if it is not refresh flow', () => { | ||
const state = { | ||
inputs: { | ||
...initialInputState, | ||
civicPass: { | ||
received: { event: CivicPassMessageEventResult.FAILURE, action: CivicPassMessageAction.CHAIN_ERROR }, | ||
}, | ||
gatewayToken: { | ||
received: undefined, | ||
}, | ||
parameters: { | ||
payer: 'test-payer', | ||
}, | ||
}, | ||
internal: { | ||
status: ExtendedGatewayStatus.CHAIN_SIGN_MESSAGE_ERROR, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
it('should set status to RESTART_REFRESH if it is a refreh flow', () => { | ||
@@ -267,4 +313,28 @@ const state = { | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.RESTART_REFRESH); | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should set status to RESTART_REFRESH if it is a refreh flow', () => { | ||
const state = { | ||
inputs: { | ||
...initialInputState, | ||
civicPass: { | ||
received: { event: CivicPassMessageEventResult.FAILURE, action: CivicPassMessageAction.CHAIN_ERROR }, | ||
}, | ||
gatewayToken: { | ||
received: { state: 'ACTIVE' }, | ||
}, | ||
parameters: { | ||
payer: 'test-payer', | ||
}, | ||
}, | ||
internal: { | ||
status: ExtendedGatewayStatus.CHAIN_SIGN_MESSAGE_ERROR, | ||
}, | ||
} as GatewayCoreState; | ||
const result = computeInternalStatus(state); | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
@@ -271,0 +341,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ExtendedGatewayStatus, GatewayCoreState, GatewayStatus } from '../../src'; | ||
import { ExtendedGatewayStatus, GatewayClientParameters, GatewayCoreState, GatewayStatus } from '../../src'; | ||
import { | ||
@@ -486,2 +486,81 @@ calculateFromGatekeeperIssuanceRequested, | ||
context('with a GatekeeperAPIStatus of requested', () => { | ||
let parameters: GatewayClientParameters; | ||
context('with a TX that can be reissued', () => { | ||
context('with a payer equal to the wallet owner', () => { | ||
beforeEach(() => { | ||
parameters = { | ||
wallet: { address: 'payer' }, | ||
payer: 'payer', | ||
} as GatewayClientParameters; | ||
}); | ||
it('should return ISSUANCE_CLIENT_SENDS_START_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
parameters, | ||
civicPass: { | ||
received: { | ||
action: 'OTHER', | ||
event: 'SUCCESS', | ||
}, | ||
}, | ||
gatekeeperRecord: { | ||
received: { | ||
state: GatekeeperAPIStatus.REQUESTED, | ||
transaction: 'transaction', | ||
payload: { | ||
preApprovedTxAvailable: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateIssuanceStatus(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_SENDS_START_NEW_TX); | ||
}); | ||
}); | ||
context('with a payer different from the wallet owner', () => { | ||
beforeEach(() => { | ||
parameters = { | ||
wallet: { address: 'payer' }, | ||
payer: 'different_payer', | ||
} as GatewayClientParameters; | ||
}); | ||
it('should return ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
parameters, | ||
civicPass: { | ||
received: { | ||
action: 'OTHER', | ||
event: 'SUCCESS', | ||
}, | ||
}, | ||
gatekeeperRecord: { | ||
received: { | ||
state: GatekeeperAPIStatus.REQUESTED, | ||
transaction: 'transaction', | ||
payload: { | ||
preApprovedTxAvailable: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateIssuanceStatus(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.ISSUANCE_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
context('if the record has a pending payload', () => { | ||
@@ -488,0 +567,0 @@ it('should return TOKEN_IN_PARTNER_REVIEW', () => { |
@@ -6,2 +6,3 @@ import { GatewayCoreState } from '../../src/types/gatewayCore'; | ||
calculateFromRefreshInReview, | ||
calculateRefreshStartPreApprovedTransaction, | ||
calculateRefreshStatus, | ||
@@ -16,2 +17,3 @@ tokenNotRefreshRequired, | ||
import { ChainConfirmationTimeout } from '../../src/utils/errors'; | ||
import { GatewayClientParameters } from '../../src/types/parameters'; | ||
@@ -288,2 +290,81 @@ describe('refresh state functions', () => { | ||
}); | ||
context('with a TX that can be reissued', () => { | ||
let parameters: GatewayClientParameters; | ||
context('with a payer the same as the wallet owner', () => { | ||
beforeEach(() => { | ||
parameters = { | ||
wallet: { address: 'payer' }, | ||
payer: 'payer', | ||
} as GatewayClientParameters; | ||
}); | ||
it('should return REFRESH_CLIENT_SENDS_START_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
parameters, | ||
civicPass: { | ||
received: { | ||
action: 'OTHER', | ||
event: 'SUCCESS', | ||
}, | ||
}, | ||
gatekeeperRecord: { | ||
received: { | ||
transaction: 'transaction', | ||
payload: { | ||
preApprovedTxAvailable: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStatus(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_START_NEW_TX); | ||
}); | ||
}); | ||
context('with a payer different from the wallet owner', () => { | ||
beforeEach(() => { | ||
parameters = { | ||
wallet: { address: 'payer' }, | ||
payer: 'different_payer', | ||
} as GatewayClientParameters; | ||
}); | ||
it('should return REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
parameters, | ||
civicPass: { | ||
received: { | ||
action: 'OTHER', | ||
event: 'SUCCESS', | ||
}, | ||
}, | ||
gatekeeperRecord: { | ||
received: { | ||
transaction: 'transaction', | ||
payload: { | ||
preApprovedTxAvailable: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStatus(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -349,2 +430,116 @@ | ||
}); | ||
context('calculateRefreshStartPreApprovedTransaction', () => { | ||
context('with a successful civic pass pre-approved tx event', () => { | ||
it('should return REFRESH_CLIENT_SENDS_REQUEST_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
received: { | ||
action: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION, | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
payload: {}, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStartPreApprovedTransaction(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_SENDS_REQUEST_NEW_TX); | ||
}); | ||
context('with a third party payer', () => { | ||
it('should return REFRESH_CLIENT_SENDS_REQUEST_NEW_TX', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
received: { | ||
action: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION, | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
payload: {}, | ||
}, | ||
}, | ||
parameters: { | ||
payer: 'payer', | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStartPreApprovedTransaction(state); | ||
// Assert | ||
expect(result).to.equal(ExtendedGatewayStatus.REFRESH_CLIENT_THIRD_PARTY_SENDS_REQUEST_NEW_TX); | ||
}); | ||
}); | ||
}); | ||
context('with an unsuccessful civic pass refresh event', () => { | ||
it('should return undefined', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
civicPass: {}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStartPreApprovedTransaction(state); | ||
// Assert | ||
expect(result).to.be.undefined; | ||
}); | ||
}); | ||
context('with a non-refresh civic pass event', () => { | ||
it('should return undefined', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
received: { | ||
action: CivicPassMessageAction.REFRESH, | ||
event: CivicPassMessageEventResult.FAILURE, | ||
payload: undefined, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStartPreApprovedTransaction(state); | ||
// Assert | ||
expect(result).to.be.undefined; | ||
}); | ||
}); | ||
context('with no payload in civic pass event', () => { | ||
it('should return undefined', () => { | ||
// Arrange | ||
const state = { | ||
inputs: { | ||
civicPass: { | ||
received: { | ||
action: CivicPassMessageAction.REFRESH, | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
payload: undefined, | ||
}, | ||
}, | ||
}, | ||
} as unknown as GatewayCoreState; | ||
// Act | ||
const result = calculateRefreshStartPreApprovedTransaction(state); | ||
// Assert | ||
expect(result).to.be.undefined; | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -64,3 +64,3 @@ import GatewayClientCore, { | ||
const proofStub = { | ||
export const mockProofObj = { | ||
proof: 'proof', | ||
@@ -134,3 +134,3 @@ signatureMethod: SignatureMethod.MESSAGE, | ||
this.proveWalletOwnershipStub = sandbox.stub(); | ||
this.proveWalletOwnershipStub.resolves(proofStub); | ||
this.proveWalletOwnershipStub.resolves(mockProofObj); | ||
this.simulateTokenChange = (token: GatewayToken) => this.onTokenChange(token); | ||
@@ -189,23 +189,3 @@ | ||
stubSuccessfulFetchCalls( | ||
{ | ||
withExistingGatekeeperRecord, | ||
getResponsePayload, | ||
postResponsePayload, | ||
payer, | ||
}: { | ||
withExistingGatekeeperRecord?: boolean; | ||
getResponsePayload?: [GatekeeperAPIStatus, Record<string, unknown>]; | ||
postResponsePayload?: Record<string, unknown>; | ||
payer?: string | undefined | null; | ||
} = { | ||
withExistingGatekeeperRecord: false, | ||
getResponsePayload: undefined, | ||
postResponsePayload: {}, | ||
payer: this.inputs.walletAddress, | ||
} | ||
) { | ||
// | ||
// stub fetch calls | ||
// | ||
stubGetFetchCall({ getResponsePayload }: { getResponsePayload: [GatekeeperAPIStatus, Record<string, unknown>] }) { | ||
// stub GK call to check for an existing record | ||
@@ -224,9 +204,26 @@ // add a delay of 100 ms to simulate an async GK response | ||
await sleep(100); | ||
if (getResponsePayload) { | ||
return getFetchStub(getResponsePayload[0], getResponsePayload[1]); | ||
} | ||
return withExistingGatekeeperRecord ? getFetchStub(200, { provider: 'web' }) : getFetchStub(404); | ||
const [status, payload] = getResponsePayload; | ||
return getFetchStub(status, payload); | ||
}); | ||
} | ||
const postRequestPayload = { | ||
stubPostFetchCall( | ||
{ | ||
postResponsePayload, | ||
payer, | ||
additionalUrlPath = '', | ||
postRequestPayload, | ||
}: { | ||
postResponsePayload?: Record<string, unknown>; | ||
payer?: string | undefined | null; | ||
additionalUrlPath?: string; | ||
postRequestPayload?: Record<string, unknown> | null; | ||
} = { | ||
postResponsePayload: {}, | ||
payer: this.inputs.walletAddress, | ||
additionalUrlPath: '', | ||
postRequestPayload: null, | ||
} | ||
) { | ||
const usePostRequestPayload = postRequestPayload || { | ||
...requestTokenPayload, | ||
@@ -237,21 +234,6 @@ address: this.inputs.walletAddress, | ||
// stub GK issuance request | ||
// add a delay of 1 seconds to simulate an async GK response | ||
console.log('fetchStub args', [ | ||
`${this.gatekeeperConfig.baseUrl}/?network=${this.inputs.network}&gatekeeperNetworkAddress=${this.inputs.gatekeeperNetwork}`, | ||
{ | ||
method: 'POST', | ||
headers: { | ||
'x-civic-flowid': sinon.match( | ||
(value: string) => value.startsWith('GWRC_'), | ||
'x-civic-flowid should start with GWRC_' | ||
), | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(postRequestPayload), | ||
signal: sinon.match.any, | ||
}, | ||
]); | ||
// add a delay of 1 second to simulate an async GK response | ||
this.fetchStub | ||
.withArgs( | ||
`${this.gatekeeperConfig.baseUrl}/?network=${this.inputs.network}&gatekeeperNetworkAddress=${this.inputs.gatekeeperNetwork}`, | ||
`${this.gatekeeperConfig.baseUrl}/${additionalUrlPath}?network=${this.inputs.network}&gatekeeperNetworkAddress=${this.inputs.gatekeeperNetwork}`, | ||
{ | ||
@@ -266,3 +248,3 @@ method: 'POST', | ||
}, | ||
body: JSON.stringify(postRequestPayload), | ||
body: JSON.stringify(usePostRequestPayload), | ||
signal: sinon.match.any, | ||
@@ -281,2 +263,112 @@ } | ||
stubFreshTransactionPostFetchCall( | ||
{ | ||
payer, | ||
}: { | ||
payer?: string | undefined | null; | ||
} = { | ||
payer: this.inputs.walletAddress, | ||
} | ||
) { | ||
const postRequestPayload = { | ||
...(payer ? { payer } : {}), | ||
}; | ||
return this.stubPostFetchCall({ | ||
payer, | ||
additionalUrlPath: `${this.inputs.walletAddress}/transaction`, | ||
postRequestPayload, | ||
}); | ||
} | ||
stubFreshTransactionRefreshPostFetchCall( | ||
{ | ||
payer, | ||
}: { | ||
payer?: string | undefined | null; | ||
} = { | ||
payer: this.inputs.walletAddress, | ||
} | ||
) { | ||
const usePostRequestPayload = { | ||
...(payer ? { payer } : {}), | ||
}; | ||
return this.stubPostFetchCall({ | ||
payer, | ||
additionalUrlPath: `${this.inputs.walletAddress}/transaction`, | ||
postRequestPayload: usePostRequestPayload, | ||
}); | ||
} | ||
stubRefreshPatchCall({ | ||
patchRequestPayload, | ||
patchResponsePayload, | ||
}: { | ||
patchRequestPayload?: Record<string, unknown> | undefined; | ||
patchResponsePayload?: Record<string, unknown> | undefined; | ||
} = {}) { | ||
const usePatchRequestPayload = patchRequestPayload || { | ||
...refreshTokenPayload, | ||
payer: this.inputs.walletAddress, | ||
}; | ||
this.fetchStub | ||
.withArgs( | ||
`${this.gatekeeperConfig.baseUrl}/${this.inputs.walletAddress}?network=${this.inputs.network}&gatekeeperNetworkAddress=${this.inputs.gatekeeperNetwork}`, | ||
{ | ||
method: 'PATCH', | ||
headers: { | ||
'x-civic-flowid': sinon.match( | ||
(value: string) => value.startsWith('GWRC_'), | ||
'x-civic-flowid should start with GWRC_' | ||
), | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(usePatchRequestPayload), | ||
signal: sinon.match.any, | ||
} | ||
) | ||
.callsFake(async () => { | ||
await sleep(110); | ||
return getFetchStub(GatekeeperAPIStatus.ISSUED, { | ||
state: GatekeeperAPIStatus.ISSUED, | ||
transaction: transactionStub, | ||
...(patchResponsePayload ? patchResponsePayload : {}), | ||
}); | ||
}); | ||
} | ||
stubSuccessfulFetchCalls( | ||
{ | ||
withExistingGatekeeperRecord, | ||
getResponsePayload, | ||
postResponsePayload, | ||
payer, | ||
postRequestPayload, | ||
}: { | ||
withExistingGatekeeperRecord?: boolean; | ||
getResponsePayload?: [GatekeeperAPIStatus, Record<string, unknown>]; | ||
postResponsePayload?: Record<string, unknown>; | ||
payer?: string | undefined | null; | ||
postRequestPayload?: Record<string, unknown> | null; | ||
} = { | ||
withExistingGatekeeperRecord: false, | ||
getResponsePayload: undefined, | ||
postResponsePayload: {}, | ||
payer: this.inputs.walletAddress, | ||
} | ||
) { | ||
const payload: [GatekeeperAPIStatus, Record<string, unknown>] = getResponsePayload | ||
? getResponsePayload | ||
: withExistingGatekeeperRecord | ||
? [GatekeeperAPIStatus.REQUESTED, { provider: 'web' }] | ||
: [GatekeeperAPIStatus.NOT_REQUESTED, {}]; | ||
this.stubGetFetchCall({ getResponsePayload: payload }); | ||
this.stubPostFetchCall({ | ||
postResponsePayload, | ||
postRequestPayload, | ||
payer, | ||
}); | ||
} | ||
simulateGatekeeperRequestTokenRejection( | ||
@@ -416,2 +508,7 @@ gatekeeperAPIStatus: GatekeeperAPIStatus = GatekeeperAPIStatus.REJECTED, | ||
expectStartNewTx() { | ||
expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.USER_INFORMATION_VALIDATED); | ||
this.expectFlowParameterInputs({ action: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION }); | ||
} | ||
expectClientSendsInReview() { | ||
@@ -422,2 +519,7 @@ expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.IN_REVIEW); | ||
expectClientSendsAwaitingConfirmation() { | ||
expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.IN_REVIEW); | ||
this.expectFlowParameterInputs({ action: CivicPassMessageAction.AWAITING_TRANSACTION_CONFIRMATION }); | ||
} | ||
expectCivicSendsInReview() { | ||
@@ -433,2 +535,7 @@ expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.IN_REVIEW); | ||
expectClientSendsRequestNewTransaction() { | ||
expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.IN_REVIEW); | ||
this.expectFlowParameterInputs({ action: CivicPassMessageAction.AWAITING_TRANSACTION_CONFIRMATION }); | ||
} | ||
prepareGKApiPollingResponse(gatekeeperAPIStatus: GatekeeperAPIStatus, payload: Record<string, unknown> = {}) { | ||
@@ -470,3 +577,3 @@ this.fetchStub | ||
async expectSuccessfulCivicSignPublicKeyRequestResponse() { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -490,3 +597,3 @@ instanceId: this.client.instanceId, | ||
async expectSuccessfulCivicSignDIDRequestResponse() { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -511,3 +618,3 @@ instanceId: this.client.instanceId, | ||
this.signMessageStub.resolves(Buffer.from('signature')); | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -527,3 +634,3 @@ instanceId: this.client.instanceId, | ||
instanceId: this.client.instanceId, | ||
data: proofStub, | ||
data: mockProofObj, | ||
}); | ||
@@ -539,3 +646,3 @@ } | ||
async simulateDataCollectionStatusEvent(validationStatus: ValidationStatus) { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -557,3 +664,3 @@ instanceId: this.client.instanceId, | ||
this.fetchStub.resetHistory(); | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -589,3 +696,3 @@ instanceId: this.client.instanceId, | ||
this.fetchStub.resetHistory(); | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -615,2 +722,27 @@ instanceId: this.client.instanceId, | ||
async simulateIframeEventTriggeringFreshTransactionRequest() { | ||
this.fetchStub.resetHistory(); | ||
this.emitter.emit('message', { | ||
data: { | ||
instanceId: this.client.instanceId, | ||
source: '', | ||
event: CivicPassMessageEventResult.SUCCESS, | ||
action: CivicPassMessageAction.START_PRE_APPROVED_TRANSACTION, | ||
// the payload for pre-approved tx is null as no POWO or checks are required | ||
payload: null, | ||
requiresProviderApproval: false, | ||
}, | ||
}); | ||
await sleep(120); | ||
// should have requested the token issuance | ||
const postMessageCallObj = this.fetchStub.getCall(0).args[1]; | ||
expect(postMessageCallObj).to.containSubset({ | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
payer: this.inputs.clientSends ? this.inputs.walletAddress : undefined, | ||
}), | ||
}); | ||
expect(this.clientOutput.gatewayStatus).to.equal(GatewayStatus.IN_REVIEW); | ||
} | ||
prepareUserAbortedTransaction() { | ||
@@ -629,3 +761,3 @@ this.handleTransactionStub.rejects(new Error('User aborted')); | ||
async simulateCivicPassInProgressEvent() { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -660,3 +792,3 @@ instanceId: this.client.instanceId, | ||
async simulateCivicPassChainFailureEvent() { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -688,3 +820,3 @@ instanceId: this.client.instanceId, | ||
} | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -761,3 +893,3 @@ instanceId: this.client.instanceId, | ||
async simulateUserFinishedFlow(eventOverrides: Partial<CivicPassMessageResponse> = {}) { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -776,3 +908,3 @@ action: CivicPassMessageAction.TOKEN_ACTIVE, | ||
async simulateUserErrorRetryFlow(eventOverrides: Partial<CivicPassMessageResponse> = {}) { | ||
await this.emitter.emit('message', { | ||
this.emitter.emit('message', { | ||
data: { | ||
@@ -779,0 +911,0 @@ action: CivicPassMessageAction.ERROR, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4213381
300
24339
197