Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions e2e/governance/uc2-approve-reject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,12 @@ check("3 PPs", list.data.data?.length, 3);
const la = list.data.data?.find((p: any) => p.label === "PP-Approve");
const lr = list.data.data?.find((p: any) => p.label === "PP-Reject");
const ln = list.data.data?.find((p: any) => p.label === "PP-None");
check("PP-Approve: ACTIVE", la?.councilMembership?.status, "ACTIVE");
check("PP-Reject: REJECTED", lr?.councilMembership?.status, "REJECTED");
check("PP-None: no council", ln?.councilMembership, null);
// provider-platform PR #103 renamed councilMembership (singular) →
// councilMemberships (plural array). A PP can be a member of multiple
// councils; this test creates exactly one membership per PP.
check("PP-Approve: ACTIVE", la?.councilMemberships?.[0]?.status, "ACTIVE");
check("PP-Reject: REJECTED", lr?.councilMemberships?.[0]?.status, "REJECTED");
check("PP-None: no council", ln?.councilMemberships?.length, 0);

// --- Test 5: Council shows both ---
console.log("\n\x1b[34m=== Test 5: Council requests list ===\x1b[0m");
Expand Down
22 changes: 22 additions & 0 deletions e2e/pos-instant/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ await Promise.all([
]);
console.log(` Funded (${elapsed()})`);

// [1b] Register pay-service as an APPROVED entity on provider-platform.
// Pay-platform submits bundles to provider-platform under its PAY_SERVICE_SK
// identity; provider-platform now gates bundle admission on the submitter
// being an APPROVED entity, so this registration is required.
console.log("\n[1b/5] Registering pay-service as APPROVED entity...");
const entityRes = await fetch(`${PROVIDER_URL}/api/v1/entities`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
pubkey: keys.payService.publicKey(),
name: "Pay Service",
jurisdictions: [],
}),
});
// 409 = already APPROVED; treat as success for idempotency.
if (!entityRes.ok && entityRes.status !== 409) {
throw new Error(
`Entity registration failed: ${entityRes.status} ${await entityRes.text()}`,
);
}
console.log(` Pay-service approved (${elapsed()})`);

// [2] Create merchant on pay-platform + store UTXOs
console.log("\n[2/5] Creating merchant account + UTXOs...");
const merchantJwt = await getPayJwt(
Expand Down
26 changes: 26 additions & 0 deletions lifecycle/ci-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ function loadEnvFile(path: string): Record<string, string> {
return env;
}

async function registerEntity(
providerUrl: string,
pubkey: string,
name: string,
): Promise<void> {
const res = await fetch(`${providerUrl}/api/v1/entities`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ pubkey, name, jurisdictions: [] }),
});
// 409 = already APPROVED; treat as success for idempotency.
if (!res.ok && res.status !== 409) {
throw new Error(
`Entity registration failed for ${pubkey}: ${res.status} ${await res
.text()}`,
);
}
}

async function fundAccount(publicKey: string): Promise<void> {
const res = await fetch(`${FRIENDBOT_URL}?addr=${publicKey}`);
if (!res.ok) {
Expand Down Expand Up @@ -198,6 +217,9 @@ async function main() {
horizonUrl,
friendbotUrl: FRIENDBOT_URL,
providerUrl: PROVIDER_URL,
// Bundles are URL-scoped to /providers/:ppPublicKey/bundles. Lifecycle
// CI runs against the single seeded PP, so ppPublicKey == ppOperator.
ppPublicKey: ppOperator.publicKey(),
channelContractId: channelContractId as ContractId,
channelAuthId: channelAuthId as ContractId,
channelAssetContractId: assetContractId as ContractId,
Expand Down Expand Up @@ -418,11 +440,15 @@ async function main() {

const aliceJwt = await authenticate(alice, e2eConfig);
console.log(" Alice authenticated");
await registerEntity(PROVIDER_URL, alice.publicKey(), "Alice");
console.log(" Alice approved as entity");
await deposit(alice.secret(), DEPOSIT_AMOUNT, aliceJwt, e2eConfig);
console.log(` Deposit ${DEPOSIT_AMOUNT} XLM complete`);

const bobJwt = await authenticate(bob, e2eConfig);
console.log(" Bob authenticated");
await registerEntity(PROVIDER_URL, bob.publicKey(), "Bob");
console.log(" Bob approved as entity");
const receiverOps = await prepareReceive(
bob.secret(),
SEND_AMOUNT,
Expand Down
30 changes: 30 additions & 0 deletions lifecycle/testnet-verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ const SEND_AMOUNT = 5;
const WITHDRAW_AMOUNT = 4;

// ─── Helpers ──────────────────────────────────────────────────────────
async function registerEntity(
providerUrl: string,
pubkey: string,
name: string,
): Promise<void> {
const res = await fetch(`${providerUrl}/api/v1/entities`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ pubkey, name, jurisdictions: [] }),
});
// 409 = already APPROVED; idempotent.
if (!res.ok && res.status !== 409) {
throw new Error(
`Entity registration failed for ${pubkey}: ${res.status} ${await res
.text()}`,
);
}
}

async function fundAccount(publicKey: string): Promise<void> {
const res = await fetch(`${FRIENDBOT_URL}?addr=${publicKey}`);
if (!res.ok && res.status !== 400) {
Expand Down Expand Up @@ -500,6 +519,10 @@ async function main() {
horizonUrl,
friendbotUrl: FRIENDBOT_URL,
providerUrl: PROVIDER_URL,
// Bundles are URL-scoped: /providers/:ppPublicKey/bundles. testnet-verify
// runs against the single PP it just registered, so ppPublicKey ==
// ppKeypair.publicKey().
ppPublicKey: ppKeypair.publicKey(),
channelContractId: channelContractId as ContractId,
channelAuthId: channelAuthId as ContractId,
channelAssetContractId: assetContractId as ContractId,
Expand Down Expand Up @@ -530,6 +553,11 @@ async function main() {
);
console.log(" Alice authenticated");

// provider-platform now gates bundle admission on the submitter's entity
// being APPROVED. Register Alice (and Bob below) before any bundle.
await registerEntity(PROVIDER_URL, alice.publicKey(), "Alice");
console.log(" Alice approved as entity");

await withE2ESpan(
"e2e.deposit",
() =>
Expand All @@ -542,6 +570,8 @@ async function main() {
() => authenticate(bob, e2eConfig),
);
console.log(" Bob authenticated");
await registerEntity(PROVIDER_URL, bob.publicKey(), "Bob");
console.log(" Bob approved as entity");

const receiverOps = await withE2ESpan(
"e2e.prepare_receive",
Expand Down
3 changes: 3 additions & 0 deletions test/setup-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ E2E_CHANNEL_ASSET_CONTRACT_ID=${assetContractId}
# Provider keypair (registered on-chain by setup)
E2E_PROVIDER_PK=${provider.publicKey()}
E2E_PROVIDER_SK=${provider.secret()}
# Bundles are URL-scoped to /providers/:ppPublicKey/bundles; in the single-PP
# e2e harness the PP key == the provider key.
E2E_PP_PUBLIC_KEY=${provider.publicKey()}

# Admin/Council keypair (for governance tests)
E2E_ADMIN_SK=${admin.secret()}
Expand Down
30 changes: 30 additions & 0 deletions testnet/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ const SEND_AMOUNT = 5;
const WITHDRAW_AMOUNT = 4;

// ─── Helpers ────────────────────────────────────────────────────────
async function registerEntity(
providerUrl: string,
pubkey: string,
name: string,
): Promise<void> {
const res = await fetch(`${providerUrl}/api/v1/entities`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ pubkey, name, jurisdictions: [] }),
});
// 409 = already APPROVED; idempotent.
if (!res.ok && res.status !== 409) {
throw new Error(
`Entity registration failed for ${pubkey}: ${res.status} ${await res
.text()}`,
);
}
}

async function fundAccount(publicKey: string): Promise<void> {
const res = await fetch(`${FRIENDBOT_URL}?addr=${publicKey}`);
if (!res.ok && res.status !== 400) {
Expand Down Expand Up @@ -455,6 +474,10 @@ async function main() {
horizonUrl,
friendbotUrl: FRIENDBOT_URL,
providerUrl: PROVIDER_URL,
// Bundles are URL-scoped: /providers/:ppPublicKey/bundles. testnet/main
// runs against the single PP it registered above, so ppPublicKey ==
// ppOperator.publicKey().
ppPublicKey: ppOperator.publicKey(),
channelContractId: channelContractId as ContractId,
channelAuthId: channelAuthId as ContractId,
channelAssetContractId: assetContractId as ContractId,
Expand Down Expand Up @@ -491,6 +514,13 @@ async function main() {
);
console.log(" Bob authenticated");

// provider-platform now gates bundle admission on the submitter's entity
// being APPROVED. Register Alice and Bob via POST /api/v1/entities before
// any deposit / send / withdraw.
await registerEntity(PROVIDER_URL, alice.publicKey(), "Alice");
await registerEntity(PROVIDER_URL, bob.publicKey(), "Bob");
console.log(" Alice + Bob approved as entities");

await withE2ESpan(
"e2e.deposit",
() =>
Expand Down
Loading