Skip to content

Commit

Permalink
add customer polling to canCreateTransaction (#102)
Browse files Browse the repository at this point in the history
* add customer polling to canCreateTransaction
  • Loading branch information
stfung77 authored Nov 11, 2022
1 parent 5cf2e4d commit 39a1047
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
3 changes: 3 additions & 0 deletions @stellar/anchor-tests/src/schemas/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const sep31ConfigSchema = {
transactionFields: {
type: "object",
},
customerPollingTimeout: {
type: "number",
},
},
required: [
"sendingAnchorClientSecret",
Expand Down
101 changes: 101 additions & 0 deletions @stellar/anchor-tests/src/tests/sep31/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
getTransactionSchema,
} from "../../schemas/sep31";
import { hasExpectedAssetEnabled } from "./info";
import { URLSearchParams } from "url";
import { hasKycServerUrl } from "../sep12/toml";

const postTransactionsGroup = "POST /transactions";
const getTransactionsGroup = "GET /transactions/:id";
Expand Down Expand Up @@ -56,12 +58,14 @@ const canCreateTransaction: Test = {
group: postTransactionsGroup,
dependencies: [
hasDirectPaymentServer,
hasKycServerUrl,
hasExpectedAssetEnabled,
differentMemosSameAccount,
],
context: {
expects: {
directPaymentServerUrl: undefined,
kycServerUrl: undefined,
sendingAnchorClientKeypair: undefined,
sendingAnchorToken: undefined,
sendingCustomerId: undefined,
Expand All @@ -88,6 +92,17 @@ const canCreateTransaction: Test = {
"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0031.md#post-transactions",
},
},
CUSTOMER_NOT_ACCEPTED: {
name: "customer's status not accepted",
text(args: any): string {
return (
"Timed out waiting for customer(s) specified for the SEP31 transaction to be in " +
"'ACCEPTED' status " +
"Errors:\n\n" +
`${args.errors}`
);
},
},
...genericFailures,
},
async run(config: Config): Promise<Result> {
Expand All @@ -97,6 +112,92 @@ const canCreateTransaction: Test = {
// but to satisfy TypeScript we make these checks here.
throw "improperly configured";
}

async function pollCustomerAccepted(
getCustomerNetworkCall: NetworkCall,
timeout: number,
) {
let startedAt = Date.now();
let timeoutMs = timeout * 1000;
while (startedAt + timeoutMs > Date.now()) {
const resBody = await makeRequest(
getCustomerNetworkCall,
200,
result,
"application/json",
);
if (resBody.status === "ACCEPTED") {
return;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
let customerId = getCustomerNetworkCall.request.url.split("id=")[1];
throw `timed out pulling customer ${customerId} for ACCEPTED status`;
}

function generateGetCustomerNetworkCall(
kycServerUrl: string,
customerId: string,
token: string,
): NetworkCall {
const requestParamsObj: Record<string, string> = {
id: customerId,
};

const customerType =
config?.sepConfig?.["12"]?.customers?.[
config?.sepConfig?.["12"]?.createCustomer
].type;

if (customerType) requestParamsObj["type"] = customerType;
const searchParams = new URLSearchParams(requestParamsObj);

const getCustomerCall: NetworkCall = {
request: new Request(
kycServerUrl + `/customer?${searchParams.toString()}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
),
};
return getCustomerCall;
}

const getSendingCustomerNetworkCall = generateGetCustomerNetworkCall(
this.context.expects.kycServerUrl,
this.context.expects.sendingCustomerId,
this.context.expects.sendingAnchorToken,
);

const getReceivingCustomerNetworkCall = generateGetCustomerNetworkCall(
this.context.expects.kycServerUrl,
this.context.expects.receivingCustomerId,
this.context.expects.sendingAnchorToken,
);

const customerPollingTimeout =
config.sepConfig["31"].customerPollingTimeout || 30;

try {
await Promise.all([
pollCustomerAccepted(
getReceivingCustomerNetworkCall,
customerPollingTimeout,
),
pollCustomerAccepted(
getSendingCustomerNetworkCall,
customerPollingTimeout,
),
]);
} catch (err) {
result.failure = makeFailure(this.failureModes.CUSTOMER_NOT_ACCEPTED, {
errors: err,
});
return result;
}

const postTransactionsCall: NetworkCall = {
request: new Request(
this.context.expects.directPaymentServerUrl + "/transactions",
Expand Down
7 changes: 7 additions & 0 deletions @stellar/anchor-tests/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ export interface Sep31Config {
* contain a value for every required field.
*/
transactionFields?: any;

/**
* Before the SEP-31 canCreateTransaction test runs, it will poll the status of the customers created in the SEP-12 test and
* check that their status is `ACCEPTED`. customerPollingTimeout is the timeout value (seconds) for polling the customer's status.
* Defaults to 30 seconds.
*/
customerPollingTimeout?: number;
}

/**
Expand Down

0 comments on commit 39a1047

Please sign in to comment.