Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.

Commit 0a3dbb4

Browse files
authored
Move and update Python examples from didkit (#6)
Also: - Fix CD - Add CI Related to didkit#308
1 parent 503a337 commit 0a3dbb4

File tree

39 files changed

+1124
-210
lines changed

39 files changed

+1124
-210
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: CI
2+
3+
on: push
4+
5+
jobs:
6+
CI:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-python@v2
11+
with:
12+
python-version: "3.10"
13+
- name: Build Wheel
14+
uses: messense/maturin-action@v1
15+
with:
16+
manylinux: off
17+
args: --find-interpreter
18+
- uses: abatilo/[email protected]
19+
- name: Run Tests
20+
working-directory: pydidkit_tests
21+
run: |
22+
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
23+
poetry install
24+
poetry run pytest

.github/workflows/release.yml

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: CI/CD
1+
name: CD
22

33
on:
44
push:
@@ -21,12 +21,7 @@ jobs:
2121
uses: messense/maturin-action@v1
2222
with:
2323
target: ${{ matrix.target }}
24-
args: --release --out dist --no-sdist
25-
- name: Install built wheel
26-
if: matrix.target == 'x64'
27-
run: |
28-
pip install didkit --no-index --find-links dist --force-reinstall
29-
python -c "import didkit"
24+
args: --release -o dist --find-interpreter
3025
- name: Upload wheels
3126
uses: actions/upload-artifact@v2
3227
with:
@@ -44,12 +39,7 @@ jobs:
4439
uses: messense/maturin-action@v1
4540
with:
4641
target: ${{ matrix.target }}
47-
args: --release --out dist --no-sdist
48-
- name: Install built wheel
49-
if: matrix.target == 'x64'
50-
run: |
51-
pip install didkit --no-index --find-links dist --force-reinstall
52-
python -c "import didkit"
42+
args: --release -o dist --find-interpreter
5343
- name: Upload wheels
5444
uses: actions/upload-artifact@v2
5545
with:
@@ -70,12 +60,7 @@ jobs:
7060
with:
7161
target: ${{ matrix.target }}
7262
manylinux: auto
73-
args: --release --out dist
74-
- name: Install built wheel
75-
if: matrix.target == 'x86_64'
76-
run: |
77-
pip install didkit --no-index --find-links dist --force-reinstall
78-
python -c "import didkit"
63+
args: --release -o dist --find-interpreter
7964
- name: Upload wheels
8065
uses: actions/upload-artifact@v2
8166
with:

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ crate-type = ["cdylib"]
2020
didkit_core = { version = "0.4", default-features = false, features = ["secp256k1", "p256", "no-ring"], package = "didkit" }
2121
serde_json = "1.0"
2222

23-
pyo3 = { version = "0.15", features = ["extension-module"] }
24-
pyo3-asyncio = { version = "0.15", features = ["tokio-runtime"] }
23+
pyo3 = { version = "0.16", features = ["extension-module"] }
24+
pyo3-asyncio = { version = "0.16", features = ["tokio-runtime"] }
2525
tokio = "1.17"
2626

2727
[build-dependencies]

examples/python-flask/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
key.jwk
2+
**/__pycache__/
3+
dist

examples/python-flask/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Flask Example
2+
3+
This project demonstrates use of verifiable credentials and presentation for an
4+
application.
5+
6+
## Dependencies
7+
8+
- Poetry ([installation instructions](https://python-poetry.org/docs/#installation))
9+
- Python 3.7 or higher
10+
11+
### Python dependencies
12+
13+
```bash
14+
$ poetry install
15+
```
16+
17+
## Running
18+
19+
```bash
20+
$ poetry run main
21+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = "0.1.0"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import json
2+
import uuid
3+
from datetime import datetime, timedelta
4+
5+
from didkit import issue_credential, key_to_did, key_to_verification_method
6+
7+
8+
async def req_issue_vc(request):
9+
with open("key.jwk", "r") as f:
10+
key = f.readline()
11+
f.close()
12+
13+
did_key = request.form.get("subject_id", key_to_did("key", key))
14+
verification_method = await key_to_verification_method("key", key)
15+
issuance_date = datetime.utcnow().replace(microsecond=0)
16+
expiration_date = issuance_date + timedelta(weeks=24)
17+
18+
credential = {
19+
"id": "urn:uuid:" + uuid.uuid4().__str__(),
20+
"@context": [
21+
"https://www.w3.org/2018/credentials/v1",
22+
"https://www.w3.org/2018/credentials/examples/v1",
23+
],
24+
"type": ["VerifiableCredential"],
25+
"issuer": did_key,
26+
"issuanceDate": issuance_date.isoformat() + "Z",
27+
"expirationDate": expiration_date.isoformat() + "Z",
28+
"credentialSubject": {
29+
"@context": [{"username": "https://schema.org/Text"}],
30+
"id": "urn:uuid:" + uuid.uuid4().__str__(),
31+
"username": "Someone",
32+
},
33+
}
34+
35+
didkit_options = {
36+
"proofPurpose": "assertionMethod",
37+
"verificationMethod": verification_method,
38+
}
39+
40+
credential = await issue_credential(
41+
credential.__str__().replace("'", '"'),
42+
didkit_options.__str__().replace("'", '"'),
43+
key,
44+
)
45+
return json.loads(credential)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import errno
2+
import json
3+
import os
4+
from socket import AF_INET, SOCK_DGRAM, socket
5+
6+
from didkit import generate_ed25519_key
7+
from flask import Flask, jsonify, render_template, request
8+
from flask_qrcode import QRcode
9+
10+
from didkit_flask.issue_credential import req_issue_vc
11+
12+
app = Flask(__name__)
13+
qrcode = QRcode(app)
14+
15+
16+
@app.route("/")
17+
def index():
18+
s = socket(AF_INET, SOCK_DGRAM)
19+
try:
20+
s.connect(("10.255.255.255", 1))
21+
IP = s.getsockname()[0]
22+
except Exception:
23+
IP = "127.0.0.1"
24+
finally:
25+
s.close()
26+
27+
url = (
28+
(request.is_secure and "https://" or "http://")
29+
+ IP
30+
+ ":"
31+
+ request.host.split(":")[-1]
32+
+ "/wallet"
33+
)
34+
35+
return render_template("index.html", url=url)
36+
37+
38+
@app.route("/credential", methods=["GET", "POST"])
39+
async def credential():
40+
credential = json.dumps(await req_issue_vc(request), indent=2, sort_keys=True)
41+
42+
return render_template("credential.html", credential=credential)
43+
44+
45+
@app.route("/wallet", methods=["GET", "POST"])
46+
async def wallet():
47+
credential = await req_issue_vc(request)
48+
if request.method == "GET":
49+
return jsonify({"type": "CredentialOffer", "credentialPreview": credential})
50+
elif request.method == "POST":
51+
return jsonify(credential)
52+
53+
54+
def main():
55+
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
56+
try:
57+
file_handle = os.open("key.jwk", flags)
58+
except OSError as e:
59+
if e.errno == errno.EEXIST:
60+
pass
61+
else:
62+
raise
63+
else:
64+
with os.fdopen(file_handle, "w") as file_obj:
65+
file_obj.write(generate_ed25519_key())
66+
app.run(host="0.0.0.0", port=5001)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
6+
<title>DIDKit Django</title>
7+
</head>
8+
<body class="h-screen w-screen flex">
9+
<pre class="whitespace-pre-wrap m-auto">{{ credential }}</pre>
10+
</body>
11+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
6+
<title>DIDKit Django</title>
7+
</head>
8+
<body class="flex flex-col items-center justify-center h-screen w-screen">
9+
<form class="flex items-center justify-center mb-4" method="post" action="/credential">
10+
<input type="text" placeholder="Enter your DID:" class="h-12 p-4 border border-blue-900 rounded mr-4" name="subject_id" />
11+
<button
12+
class="h-12 p-2 border border-blue-900 rounded"
13+
type="submit"
14+
>
15+
Get credential
16+
</button>
17+
</form>
18+
<p>or scan the QRCode bellow with your wallet. i.e: Credible</p>
19+
<div class="my-8"><img src={{ qrcode(url) }} class="w-32 h-32"></div>
20+
<p>or</p>
21+
<a href="/credential">
22+
<button
23+
class="h-12 p-2 border mt-6 border-blue-900 rounded"
24+
type="submit"
25+
>
26+
Get server issued credential
27+
</button>
28+
</a>
29+
</body>
30+
</html>

0 commit comments

Comments
 (0)