<jupyter_start><jupyter_text>The InterlockLedger RESTful APIThis notebook will show the usage of some features of the Python client of the InterlockLedger RESTful API.<jupyter_code>%load_ext autoreload
%autoreload 2

import sys
import traceback
import json
#sys.path.append('../')

from il2_rest import RestNode
from il2_rest.util import PKCS12Certificate

# Comment these two lines if you want to show InsecureRequestWarnings
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)<jupyter_output><empty_output><jupyter_text>Getting an instance of a nodeTo use the `il2_rest` client, you need to create an instance of the `RestNode` by passing a certificate file and the address of the node (default address is `localhost`). > The PKCS12 certificate must be already imported to the InterlockLedger node and be permissioned on the desired chain. See the InterlockLedger node manual.With the `RestNode` class, it is possible to retrieve details of the node, such as the list of valid apps in the network, peers, mirrors and chains.<jupyter_code>address = 'minerva-data.il2.io'
port = 32094
cert_file = 'danielchino.api.pfx'
with open('password.details','r') as f :
    cert_pass = f.readline()

node = RestNode(cert_file = cert_file, cert_pass = cert_pass, port = port, address=address)
print(node.details)<jupyter_output><empty_output><jupyter_text>Exploring the chainsTo see and store records and documents, you need to use an instance of the `RestChain`. You can get `RestChain` instances by retrieving the list of chains in the network:<jupyter_code>chains = node.chains
for chain in chains :
    print(chain)
chain_id = chains[0].id<jupyter_output><empty_output><jupyter_text>Checking the content of a chainBy getting an instance of the `RestChain`, it is possible to retrieve and send information about the chain.On this example, we will use the chain with the following id (`chain_id` - change this to your il2 chain).It is possible to see the permitted apps and keys.It is also possible to check the records stored in the chain.<jupyter_code>chain = node.chain_by_id(chain_id)

print(chain.active_apps)

for key in chain.permitted_keys :
    print(key)

for record in chain.records(firstSerial=0, lastSerial=2).items :
    print(record)<jupyter_output><empty_output><jupyter_text>Creating a ChainIf your are using a certificate with administration privileges, it is possible to create new chains.<jupyter_code>from il2_rest.models import ChainCreationModel

new_chain = ChainCreationModel(
    name = 'IL2App Chain',
    description = 'Chain to store person enrollments',
    managementKeyPassword = '<PASSWORD>',
    emergencyClosingKeyPassword = '<PASSWORD>'
)

created_chain = node.create_chain(model=new_chain)
print(created_chain)<jupyter_output><empty_output><jupyter_text>Managing Keys and AppsIf your are using a certificate allowed to permit key, you can permit other keys in the chain. The `permit_keys` method will return the list of permitted keys in the chain.> To permit other keys, the certificate must be already imported to the Interlockledger node with actions for App 2 and actions 500,501.<jupyter_code>from il2_rest.models import KeyPermitModel
from il2_rest.enumerations import KeyPurpose

chain = node.chain_by_id(chain_id)

try :
    key_model = KeyPermitModel(app = 4, appActions = [1000, 1001], key_id = 'Key!MJ0kidltB324mfkiOG0aBlEocPA#SHA1',
                       name = 'documenter', publicKey = '<KEY>',
                       purposes = [KeyPurpose.Action, KeyPurpose.Protocol])
    keys = chain.permit_keys([key_model])
    for key in keys:
        print(key)
except :
    print(traceback.format_exc())<jupyter_output><empty_output><jupyter_text>Similarly, you can permit apps using the following method. In this example we are trying to permit the app 4 (to store documents).<jupyter_code>chain = node.chain_by_id(chain_id)

try :
    apps = chain.permit_apps([4])
    print(apps)
except :
    print(traceback.format_exc())<jupyter_output><empty_output><jupyter_text>Storing DocumentsYou can store a series of documents in a single record using the documents API. To do so, you need to start a transaction, then you upload the documents and finally commit the transaction.> Whe you commit the documents, you will receive the locator of the documents, remember to store this locator in your system.<jupyter_code>from il2_rest.models import DocumentsBeginTransactionModel
from il2_rest.models import DocumentsTransactionModel

print(str(node.documents_config))

chain = node.chain_by_id(chain_id)

# Using a DocumentsBeginTransactionModel
try :
    model = DocumentsBeginTransactionModel(chain = chain_id, 
                                           comment ='Using model',
                                           encryption = 'PBKDF2-SHA256-AES128-HIGH',
                                           password = '<PASSWORD>')
    resp = chain.documents_begin_transaction(model = model)
    transaction_id = resp.transactionId
   
    print(chain.documents_transaction_add_item(transaction_id, "item1.txt", "./test.txt"))
    print(chain.documents_transaction_add_item(transaction_id, "item2.txt", "./test2.txt", comment = "This file has a comment."))
    print(chain.documents_transaction_add_item(transaction_id, "item3.pdf", "../InterlockLedgerAPI.pdf", comment = "PDF file."))
    
       
    print(chain.documents_transaction_status(transaction_id))
    
    locator = chain.documents_transaction_commit(transaction_id)
    print(locator)
except :
    print(traceback.format_exc())

# Passing parameters to the documents_begin_transaction method
try :
    resp = chain.documents_begin_transaction(comment ='Using parameters')
    transaction_id = resp.transactionId
   
    print(chain.documents_transaction_add_item(transaction_id, "item1.txt", "./test.txt"))
    print(chain.documents_transaction_add_item(transaction_id, "item2.txt", "./test2.txt", comment = "This file has a comment."))
       
    print(chain.documents_transaction_status(transaction_id))
    
    locator = chain.documents_transaction_commit(transaction_id)
    print(locator)
except :
    print(traceback.format_exc())<jupyter_output><empty_output><jupyter_text>To get information about a multi-document record, you will need to use the locator id. With the locator id you can check the metadata of a multi-document. Or you can download the files stored in the record.It is possible to download a single file (indicating the file with its index), or download all files in a compressed file.<jupyter_code>chain = node.chain_by_id(chain_id)

resp = chain.documents_transaction_metadata(locator)
print(resp)
# Download a single file
chain.download_single_document_at(locator, 1)

# Download a compressed file with all files in the record
chain.download_documents_as_zip(locator)<jupyter_output><empty_output><jupyter_text>Storing JSON DocumentsIf you wish to store a generic JSON data, you can use the following script to store in a JSON document record:<jupyter_code>chain = node.chain_by_id(chain_id)

json_data = {
    "field1" : 1,
    "field2" : "Test",
    "field3": [1,2,3],
    "field4" : {
        "value1" : 10,
        "value2" : 20
    }
}

resp = chain.store_json_document(json_data)
print(resp)<jupyter_output><empty_output><jupyter_text>Decrypting the JSON Document<jupyter_code>pkcs12_cert = PKCS12Certificate(path = cert_file, password = cert_pass)
decrypted_json = resp.encryptedJson.decode_with(pkcs12_cert)
print(json.dumps(decrypted_json, indent=4))<jupyter_output><empty_output><jupyter_text>Storing RecordsThere is also a generic interface to store records. It is possible to store records using the model classes or using the unpacked method.> To use this method, you will need to know the exact record's logic schema of the InterlockApp (`applicationId`) you want to store -- either JSON or bytewise.> If you are using InterlockApps 4 (Multi-Document) or 8 (JSON Documents), we highly recommend to use the specific methods for each app.<jupyter_code>from il2_rest.models import NewRecordModelAsJson
from il2_rest.models import NewRecordModel

chain = node.chain_by_id(chain_id)

try :
    model_json = NewRecordModelAsJson(applicationId = 1, payloadTagId = 300, rec_json= {'tagId': 300,'version' : 1, 'apps': [4]})
    record_json = chain.add_record_as_json(model = model_json)
    print(record_json)
except :
    print(traceback.format_exc())

try :
    model_bytes = NewRecordModel(applicationId = 1, payloadTagId = 300, payloadBytes = bytes([248, 52, 7, 5, 0, 0, 20, 2, 1, 4]))
    record_bytes = chain.add_record(model_bytes)
    print(record_bytes)
except :
    print(traceback.format_exc())

try :
    record_unpacked = chain.add_record_unpacked(applicationId = 1, payloadTagId = 300, rec_bytes = bytes([5, 0, 0, 20, 2, 1, 4]))
    print(record_unpacked)
except :
    print(traceback.format_exc())<jupyter_output><empty_output><jupyter_text>InterlockingsIt is also possible to check or force interlocks using the API.<jupyter_code>from il2_rest.models import ForceInterlockModel

chain = node.chains[0]

for interlock in chain.interlocks().items :
    print(interlock)
    break
    
force_model = ForceInterlockModel(targetChain = 'or7lzOGOvzH3GeNUTPqJI41CY0rVcEWgw6IEBmSSDxI')
interlock_model = chain.force_interlock(model = force_model)
print(interlock_model)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0833867179158659, 'fraction_numerical': 0.014734144778987828, 'mean_word_length': 4.932235592146928, 'pattern_counts': {'":': 1, '<': 57, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 13, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '17870', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2927, 'n_tokens_neox': 2797, 'n_words': 856, 'path': 'sample/Using the il2_rest client.ipynb', 'repo_name': 'interlockledger/interlockledger-rest-client-python', 'size': '9745'}