OriginStamp Python|Golang SDK Examples
- 4 minutes read - 746 wordsA friend mentioned OriginStamp to me.
NB There are 2 sites: originstamp.com and originstamp.org.
It’s an interesting project.
It’s a solution for providing auditable proof that you had a(ccess to) some digital thing before a certain date. OriginStamp provides user-|developer-friendly means to submit files|hashes (of your content) and have these bundled into transactions that are submitted to e.g. bitcoin.
I won’t attempt to duplicate the narrative here, review OriginStamp’s site and some of its content.
What I did find more challenging than I should have, is writing quick-hit samples. This may be due to my lack of familiarity with Swagger-generated SDKs.
Python
A Python SDK is published and so, let’s enrich that slightly for starters:
All using Python3 now, hopefully:
DIR="[[SOME-PROJECT-DIR]]/python"
python3 -m venv ${DIR}/venv
source ${DIR}/venv/bin/activate
requirements.txt:
originstamp-client==1.0.3
NB Don’t take my word for it, see PyPi’s originstamp-client
listing
AsideOne experiment I’ve made with Google’s Trillian is an as-yet non-public PyPi Transparency Client. Writing this, I got a slightly better understanding of the mechanism underpinning PyPi. PyPi – unsurprisingly – uses hashes as a way to provide (though not enforce) tamperproofing. The SHA256 for the wheel (!) for
originstamp-client
(1.0.3) isd2fe59604eeab59919fc8b261490f80a1f5f4fc93cddfe9f6d5a2bf44033262b
(the BLAKE2 is3200bd1d09baac20b7a3a295f5b2c798d8daf028f864212288e2d0fabd2bf6f5
). See link. It would be interesting to use the following samples to submit timestamps of this library (and perhaps of the samples themselves) to OriginStamp. I’ll leave that to you to try!
python.py:
from __future__ import print_function
import argparse
import hashlib
import originstamp_client as client
import time
from originstamp_client.rest import ApiException
from pprint import pprint
parser = argparse.ArgumentParser(
description="Test OriginStamp Python SDK"
)
parser.add_argument(
"--api_key",
help="OriginStamp API Key",
required=True,
)
parser.add_argument(
"--email",
help="Email address to receive notifications",
required=True,
)
args = parser.parse_args()
api_instance = client.TimestampApi()
s = b"Frederik Jack is a bubbly Border Collie"
h = hashlib.sha256(s).hexdigest()
print(h)
rqst = client.TimestampRequest(
comment="FrederikJack test",
hash=h,
notifications=[
client.Notification(
currency=0,
notification_type=0,
target=args.email,
)
],
)
try:
resp = api_instance.create_timestamp(
args.api_key,
rqst,
)
pprint(resp)
except ApiException as e:
print("Exception calling create_timestamp: %s\n", e)
You can run this from the command-line
python3 python.py --api_key=${API_KEY} --email=${EMAIL}
Or create a Visual Studio Code launch.json
similar to:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {},
"args": [
"--api_key=[API_KEY]",
"--email=[EMAIL]",
]
}
]
}
You receive a response of the form:
{'data': {'comment': None,
'created': False,
'date_created': 1581969171289,
'hash_string': '037e945cf8da5945acbcf2390c71a497c6edefdc364ada1f33d76a2b5f8b472b',
'timestamps': [...]},
'error_code': 0,
'error_message': None}
NB I didn’t expect the comment
value in the response to be None
(API documentation)
NB The hash (037e945cf8da5945acbcf2390c71a497c6edefdc364ada1f33d76a2b5f8b472b
) corresponds to the SHA-256 of the string in the sample; you should be able to verify this value.
Golang
This took a little more ’tweaking’ :-(
The SDK is available from the web site but is not published (!?) to GitHub OriginStamp
Navigate to https://originstamp.org/dev and choose “Go” from the “Download Client Code” under “Integrate OriginStamp into Existing Services” section.
The README that’s included suggests incorporating the SDK into your project.
I chose to keep it separate using Modules. Your choice.
Assuming:
DIR="[[SOME-PROJECT-DIR]]/golang"
${DIR}
├── go-client
└── main
I added a go.mod
file to the OriginStamp SDK (naming it github.com/OriginStampTimestamping/originstamp-client-golang
to be consistent with the other SDKs)
and then created a go.mod
for my package:
module github.com/[YOUR-GITHUB]/originstamp
go 1.13
replace github.com/OriginStampTimestamping/originstamp-client-golang => ../go-client
require (
github.com/OriginStampTimestamping/originstamp-client-golang v0.0.1
)
The roughly equivalent Golang code is:
package main
import (
"context"
"crypto/sha256"
"flag"
"fmt"
"log"
api "github.com/OriginStampTimestamping/originstamp-client-golang"
)
var (
apiKey = flag.String("api_key", "", "OriginStamp API Key")
email = flag.String("email", "", "Email for Notifications")
)
func main() {
flag.Parse()
if *apiKey == "" {
log.Fatal("expect '--api_key'")
}
client := api.NewAPIClient(api.NewConfiguration())
s := "Frederik Jack is a bubbly Border Collie"
h := sha256.Sum256([]byte(s))
log.Printf("%x\n", h)
rqst := api.TimestampRequest{
Comment: "FrederikJack test",
Hash: fmt.Sprintf("%x", h),
Notifications: []api.Notification{
{
Currency: 0,
NotificationType: 0,
Target: *email,
},
},
}
resp, httpResp, err := client.TimestampApi.CreateTimestamp(
context.Background(),
*apiKey,
rqst,
)
if err != nil {
log.Println(err)
}
log.Printf("Response:\n%+v\n", resp)
log.Printf("HTTP:\n%+v\n", httpResp)
}
and, of course:
go run main.go --api_key=${API_KEY} --email=${EMAIL}
Go’s %+v
isn’t as ‘pretty’ as Python’s. One option is to print resp.Data
instead.
A slightly better approach is:
pretty, err := json.MarshalIndent(resp, "", " ")
if err != nil {
log.Fatal(err)
}
log.Printf("Response:\n%+v\n", string(pretty))
This results in something similar to:
2020/02/17 14:20:02 037e945cf8da5945acbcf2390c71a497c6edefdc364ada1f33d76a2b5f8b472b
2020/02/17 14:20:02 Request:
{Comment:FrederikJack test Hash:037e945cf8da5945acbcf2390c71a497c6edefdc364ada1f33d76a2b5f8b472b Notifications:[{Currency:0 NotificationType:0 Target:...}] Url:}
2020/02/17 14:20:02 Response:
{
"data": {
"date_created": 1581969171289,
"hash_string": "037e945cf8da5945acbcf2390c71a497c6edefdc364ada1f33d76a2b5f8b472b",
"timestamps": [...]
}
}
2020/02/17 14:20:02 HTTP:
&{Status:200 OK StatusCode:200 ... }
NB The hash (as expected) is the same everywhere.
NB The StatusCode is 200
(success)