Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
68e76af
feat(sdk/python): Update dstack python SDK.
Leechael Aug 12, 2025
cba7690
imp(sdk/python): test cases for AsyncTappdClient & added version header
Leechael Aug 14, 2025
46399c2
chore(sdk): added test output scripts to compare implementations acro…
Leechael Aug 14, 2025
4310288
docs(sdk/python): add AI generated docs.
Leechael Aug 14, 2025
09a7450
docs(sdk/python): added explaination for sync & async.
Leechael Aug 14, 2025
b3038e0
refactor(sdk/python): update RPC method calls to use method names ins…
kvinwang Aug 15, 2025
8704adc
refactor(sdk/python): simplify is_reachable methods to use _send_rpc_…
kvinwang Aug 15, 2025
faeffc2
sdk/python: Reuse code logic between async and sync clients
kvinwang Aug 15, 2025
215a968
imp: typing for the new universal client model & share TCP connection…
Leechael Aug 15, 2025
8579545
imp: set default timeout for api client.
Leechael Aug 15, 2025
98fd721
fix: typing & errors after fix conflict
Leechael Aug 15, 2025
3ad0da1
chore: SPDX
Leechael Aug 15, 2025
3220ce6
refactor: back to decorator
Leechael Aug 16, 2025
0dd1c66
fix: more accurately test for deprecated warning count
Leechael Aug 16, 2025
ca96a36
sdk/python: Remove unecessary call_async_with_deprecation
kvinwang Aug 18, 2025
50d8122
sdk/python: delegate __enter__ with @call_async
kvinwang Aug 18, 2025
06fe9a9
sdk/python: ruff format
kvinwang Aug 18, 2025
268be67
build: use ruffy & pdm.
Leechael Aug 18, 2025
69be206
chore: fmt
Leechael Aug 18, 2025
0f4a92a
chore: bump python-sdk to 0.5.0
Leechael Aug 18, 2025
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
158 changes: 158 additions & 0 deletions sdk/js/test-outputs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#!/usr/bin/env node
// SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
//
// SPDX-License-Identifier: Apache-2.0

const { DstackClient, TappdClient, getComposeHash, verifyEnvEncryptPublicKey } = require('./dist/node/index.js');
const { toViemAccount, toViemAccountSecure } = require('./dist/node/viem.js');
const { toKeypair, toKeypairSecure } = require('./dist/node/solana.js');

async function main() {
console.log("=== JS SDK Output Test ===");

try {
// Test client get_key
const client = new DstackClient();
console.log("\n1. Testing DstackClient.getKey()");

const testPaths = [
{ path: "test/wallet", purpose: "ethereum" },
{ path: "test/signing", purpose: "solana" },
{ path: "user/alice", purpose: "mainnet" }
];

for (const { path, purpose } of testPaths) {
const keyResult = await client.getKey(path, purpose);
console.log(`getKey('${path}', '${purpose}'):`);
console.log(` key: ${Buffer.from(keyResult.key).toString('hex')}`);
console.log(` signature_chain length: ${keyResult.signature_chain.length}`);
console.log(` signature_chain[0]: ${Buffer.from(keyResult.signature_chain[0]).toString('hex')}`);
}

// Test viem integration
console.log("\n2. Testing Viem Integration");
const ethKey = await client.getKey("eth/test", "wallet");

console.log("\n2.1 toViemAccount (legacy):");
try {
const account = toViemAccount(ethKey);
console.log(` address: ${account.address}`);
console.log(` type: ${account.type}`);
} catch (error) {
console.log(` error: ${error.message}`);
}

console.log("\n2.2 toViemAccountSecure:");
try {
const accountSecure = toViemAccountSecure(ethKey);
console.log(` address: ${accountSecure.address}`);
console.log(` type: ${accountSecure.type}`);
} catch (error) {
console.log(` error: ${error.message}`);
}

// Test solana integration
console.log("\n3. Testing Solana Integration");
const solKey = await client.getKey("sol/test", "wallet");

console.log("\n3.1 toKeypair (legacy):");
try {
const keypair = toKeypair(solKey);
console.log(` publicKey: ${keypair.publicKey.toString()}`);
console.log(` secretKey length: ${keypair.secretKey.length}`);
console.log(` secretKey (first 32 bytes): ${Buffer.from(keypair.secretKey.slice(0, 32)).toString('hex')}`);
} catch (error) {
console.log(` error: ${error.message}`);
}

console.log("\n3.2 toKeypairSecure:");
try {
const keypairSecure = toKeypairSecure(solKey);
console.log(` publicKey: ${keypairSecure.publicKey.toString()}`);
console.log(` secretKey length: ${keypairSecure.secretKey.length}`);
console.log(` secretKey (first 32 bytes): ${Buffer.from(keypairSecure.secretKey.slice(0, 32)).toString('hex')}`);
} catch (error) {
console.log(` error: ${error.message}`);
}

// Test TappdClient (deprecated)
console.log("\n4. Testing TappdClient (deprecated)");
try {
const tappdClient = new TappdClient();
console.log("\n4.1 TappdClient.getKey():");
const tappdKey = await tappdClient.getKey("test/wallet", "ethereum");
console.log(` key: ${Buffer.from(tappdKey.key).toString('hex')}`);
console.log(` signature_chain length: ${tappdKey.signature_chain.length}`);

console.log("\n4.2 TappdClient.tdxQuote():");
const tappdQuote = await tappdClient.tdxQuote("test-data", "raw");
console.log(` quote length: ${tappdQuote.quote.length}`);
console.log(` event_log length: ${tappdQuote.event_log.length}`);
console.log(` rtmrs count: ${tappdQuote.replayRtmrs().length}`);
} catch (error) {
console.log(` error: ${error.message}`);
}

// Test quotes
console.log("\n5. Testing Quote Methods");
console.log("\n5.1 DstackClient.getQuote():");
const dstackQuote = await client.getQuote("test-data-for-quote");
console.log(` quote length: ${dstackQuote.quote.length}`);
console.log(` event_log length: ${dstackQuote.event_log.length}`);
console.log(` rtmrs count: ${dstackQuote.replayRtmrs().length}`);

// Test getComposeHash
console.log("\n6. Testing getComposeHash");
const testComposes = [
{
manifest_version: 1,
name: "test-app",
runner: "docker-compose",
docker_compose_file: "services:\\n app:\\n image: test\\n ports:\\n - 8080:8080"
},
{
manifest_version: 1,
name: "another-app",
runner: "docker-compose",
docker_compose_file: "services:\\n web:\\n build: .\\n environment:\\n - NODE_ENV=production"
}
];

testComposes.forEach((compose, index) => {
const hash = getComposeHash(compose);
console.log(`compose ${index + 1}: ${hash}`);
console.log(` name: ${compose.name}`);
console.log(` runner: ${compose.runner}`);
});

// Test verifyEnvEncryptPublicKey
console.log("\n7. Testing verifyEnvEncryptPublicKey");
const testCases = [
{
publicKey: Buffer.from('e33a1832c6562067ff8f844a61e51ad051f1180b66ec2551fb0251735f3ee90a', 'hex'),
signature: Buffer.from('8542c49081fbf4e03f62034f13fbf70630bdf256a53032e38465a27c36fd6bed7a5e7111652004aef37f7fd92fbfc1285212c4ae6a6154203a48f5e16cad2cef00', 'hex'),
appId: '0000000000000000000000000000000000000000'
},
{
publicKey: Buffer.from('deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', 'hex'),
signature: Buffer.from('0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'hex'),
appId: 'invalid-app-id'
}
];

testCases.forEach((testCase, index) => {
try {
const result = verifyEnvEncryptPublicKey(testCase.publicKey, testCase.signature, testCase.appId);
console.log(`test case ${index + 1}: ${result ? Buffer.from(result).toString('hex') : 'null'}`);
} catch (error) {
console.log(`test case ${index + 1}: error - ${error.message}`);
}
});

} catch (error) {
console.error("Error:", error.message);
process.exit(1);
}
}

main().catch(console.error);
61 changes: 61 additions & 0 deletions sdk/python/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
#
# SPDX-License-Identifier: Apache-2.0

.PHONY: install lint format type-check type-check-tests test check-all verify

# Install dependencies including linting tools
install:
pdm install -G lint

# Run all formatters (using PDM scripts)
format:
pdm run fmt

# Alias for format
fmt: format

# Run linting tools (using PDM scripts)
lint:
pdm run lint

# Run type checking only
type-check:
pdm run mypy src/

# Run type checking on tests specifically
type-check-tests:
pdm run mypy tests/test_mypy_check.py tests/test_typing.py

# Run tests
test:
@if [ -z "$$DSTACK_SIMULATOR_ENDPOINT" ]; then \
echo "error: DSTACK_SIMULATOR_ENDPOINT environment variable is not set"; \
exit 1; \
fi
@if [ -z "$$TAPPD_SIMULATOR_ENDPOINT" ]; then \
echo "error: TAPPD_SIMULATOR_ENDPOINT environment variable is not set"; \
exit 1; \
fi
@if [[ "$$DSTACK_SIMULATOR_ENDPOINT" == /* ]] && [ ! -e "$$DSTACK_SIMULATOR_ENDPOINT" ]; then \
echo "error: dstack socket file $$DSTACK_SIMULATOR_ENDPOINT does not exist"; \
exit 1; \
fi
@if [[ "$$TAPPD_SIMULATOR_ENDPOINT" == /* ]] && [ ! -e "$$TAPPD_SIMULATOR_ENDPOINT" ]; then \
echo "error: tappd socket file $$TAPPD_SIMULATOR_ENDPOINT does not exist"; \
exit 1; \
fi
pdm run test

# Run all checks (format, lint, skip test)
check-all:
pdm run fmt
pdm run lint

# Check code without fixing (for CI)
check:
pdm run check

# Run verification without formatting (skip test)
verify:
pdm run check
Loading