Skip to content

Commit 45be770

Browse files
committed
feat(multi-asset): drive the asset-lifecycle E2E against the real council
Extend the UC6 suite to exercise the full enable/disable/re-enable mechanism on-chain, against the real council-platform watching the real chain: - provider joins the seeded council via the REAL dashboard join API (starts its on-chain watcher); membership activates from the provider_added chain event, pulling channel config (with status) from the council — no hand-seeded membership for the lifecycle assertions. - lifecycle: council disable_channel(USDC) on-chain → assert council DB tracks the chain (/public/channels status=disabled) → assert provider converged on the live event → withdraw-only enforced (deposit + send rejected, withdraw works, XLM unaffected) → enable_channel → full service resumes. - lib/admin: enable_channel/disable_channel helpers. - compose: COUNCIL_DATABASE_URL for the test-runner. Suite green via ./test.sh multi-asset.
1 parent 278500f commit 45be770

4 files changed

Lines changed: 456 additions & 80 deletions

File tree

docker-compose.multi-asset.yml

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ services:
4343
volumes:
4444
- ./.traces/multi-asset:/badger
4545
healthcheck:
46-
test: ["CMD-SHELL", "wget -qO- http://localhost:16686/api/services || exit 1"]
46+
test: [
47+
"CMD-SHELL",
48+
"wget -qO- http://localhost:16686/api/services || exit 1",
49+
]
4750
interval: 2s
4851
timeout: 3s
4952
retries: 15
@@ -61,7 +64,7 @@ services:
6164
- sh
6265
- -c
6366
- |
64-
cp test/setup-multi-asset.ts setup.ts && deno run --allow-all setup.ts
67+
cp test/setup-multi-asset.ts setup.ts && deno run --allow-all setup.ts
6568
environment:
6669
STELLAR_RPC_URL: http://stellar:8000/soroban/rpc
6770
STELLAR_NETWORK_PASSPHRASE: "Standalone Network ; February 2017"
@@ -153,28 +156,28 @@ services:
153156
- sh
154157
- -c
155158
- |
156-
mkdir -p multi-asset lib
157-
cp /multi-asset-src/*.ts multi-asset/ && cp /multi-asset-src/deno.json multi-asset/ 2>/dev/null || true
158-
cp /lib-src/*.ts lib/
159-
cp -r /lib-src/client lib/
160-
cd multi-asset && deno install && cd ..
161-
echo "Waiting for provider and Stellar..."
162-
for i in $$(seq 1 60); do
163-
provider_ok=false stellar_ok=false
164-
PROBE_URL="$$PROVIDER_URL" deno eval "try { await fetch(Deno.env.get('PROBE_URL')); Deno.exit(0) } catch { Deno.exit(1) }" 2>/dev/null && provider_ok=true
165-
PROBE_URL="$$STELLAR_RPC_URL" deno eval "
166-
const url = Deno.env.get('PROBE_URL');
167-
const r = await fetch(url, {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({jsonrpc:'2.0',id:1,method:'getHealth'})});
168-
const d = await r.json(); Deno.exit(d.result?.status==='healthy'?0:1)
169-
" 2>/dev/null && stellar_ok=true
170-
if [ "$$provider_ok" = true ] && [ "$$stellar_ok" = true ]; then
171-
echo "Provider and Stellar are ready."
172-
break
173-
fi
174-
if [ "$$i" -eq 60 ]; then echo "Services not ready after 120s"; exit 1; fi
175-
sleep 2
176-
done
177-
exec deno run --allow-all multi-asset/main.ts
159+
mkdir -p multi-asset lib
160+
cp /multi-asset-src/*.ts multi-asset/ && cp /multi-asset-src/deno.json multi-asset/ 2>/dev/null || true
161+
cp /lib-src/*.ts lib/
162+
cp -r /lib-src/client lib/
163+
cd multi-asset && deno install && cd ..
164+
echo "Waiting for provider and Stellar..."
165+
for i in $$(seq 1 60); do
166+
provider_ok=false stellar_ok=false
167+
PROBE_URL="$$PROVIDER_URL" deno eval "try { await fetch(Deno.env.get('PROBE_URL')); Deno.exit(0) } catch { Deno.exit(1) }" 2>/dev/null && provider_ok=true
168+
PROBE_URL="$$STELLAR_RPC_URL" deno eval "
169+
const url = Deno.env.get('PROBE_URL');
170+
const r = await fetch(url, {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({jsonrpc:'2.0',id:1,method:'getHealth'})});
171+
const d = await r.json(); Deno.exit(d.result?.status==='healthy'?0:1)
172+
" 2>/dev/null && stellar_ok=true
173+
if [ "$$provider_ok" = true ] && [ "$$stellar_ok" = true ]; then
174+
echo "Provider and Stellar are ready."
175+
break
176+
fi
177+
if [ "$$i" -eq 60 ]; then echo "Services not ready after 120s"; exit 1; fi
178+
sleep 2
179+
done
180+
exec deno run --allow-all multi-asset/main.ts
178181
environment:
179182
NETWORK: local
180183
PROVIDER_URL: http://provider:3000
@@ -186,6 +189,7 @@ services:
186189
FRIENDBOT_URL: http://stellar:8000/friendbot
187190
JAEGER_QUERY_URL: http://jaeger:16686
188191
DATABASE_URL: postgresql://admin:devpass@db:5432/provider_platform_db
192+
COUNCIL_DATABASE_URL: postgresql://admin:devpass@db:5432/council_platform_db
189193
WASM_DIR: /wasms
190194
OTEL_DENO: "true"
191195
OTEL_SERVICE_NAME: "moonlight-e2e"

lib/admin.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,57 @@ export async function removeProvider(
5555
console.log(" Provider removed");
5656
return result;
5757
}
58+
59+
/**
60+
* Disable an asset channel on the Channel Auth contract.
61+
* Calls disable_channel(channel, asset) — quorum/admin authorized. Emits a
62+
* channel_state_changed event (enabled=false). The contract stores no state.
63+
*/
64+
export async function disableChannel(
65+
server: rpc.Server,
66+
admin: Keypair,
67+
networkPassphrase: string,
68+
channelAuthId: string,
69+
channelContractId: string,
70+
assetContractId: string,
71+
): Promise<rpc.Api.GetSuccessfulTransactionResponse> {
72+
console.log(` Disabling channel ${channelContractId.slice(0, 8)}...`);
73+
74+
const contract = new Contract(channelAuthId);
75+
const op = contract.call(
76+
"disable_channel",
77+
new Address(channelContractId).toScVal(),
78+
new Address(assetContractId).toScVal(),
79+
);
80+
81+
const result = await submitTx(server, admin, networkPassphrase, op);
82+
console.log(" Channel disabled");
83+
return result;
84+
}
85+
86+
/**
87+
* Enable (or re-enable) an asset channel on the Channel Auth contract.
88+
* Calls enable_channel(channel, asset) — quorum/admin authorized. Emits a
89+
* channel_state_changed event (enabled=true). Re-enable reuses this call.
90+
*/
91+
export async function enableChannel(
92+
server: rpc.Server,
93+
admin: Keypair,
94+
networkPassphrase: string,
95+
channelAuthId: string,
96+
channelContractId: string,
97+
assetContractId: string,
98+
): Promise<rpc.Api.GetSuccessfulTransactionResponse> {
99+
console.log(` Enabling channel ${channelContractId.slice(0, 8)}...`);
100+
101+
const contract = new Contract(channelAuthId);
102+
const op = contract.call(
103+
"enable_channel",
104+
new Address(channelContractId).toScVal(),
105+
new Address(assetContractId).toScVal(),
106+
);
107+
108+
const result = await submitTx(server, admin, networkPassphrase, op);
109+
console.log(" Channel enabled");
110+
return result;
111+
}

multi-asset/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ services:
138138
STELLAR_NETWORK_PASSPHRASE: "Standalone Network ; February 2017"
139139
FRIENDBOT_URL: http://stellar:8000/friendbot
140140
DATABASE_URL: postgresql://admin:devpass@db:5432/multi_asset_db
141+
COUNCIL_DATABASE_URL: postgresql://admin:devpass@council-db:5432/council_multi_asset_db
141142
WASM_DIR: /wasms
142143
entrypoint:
143144
- sh

0 commit comments

Comments
 (0)