feat: add interactive token deployment
This commit is contained in:
parent
1498edbb07
commit
d3f65798f1
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,9 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
*.pyc
|
*.pyc
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
.venv
|
||||||
|
build
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
contracts
|
||||||
|
*.egg
|
0
cic/actions/__init__.py
Normal file
0
cic/actions/__init__.py
Normal file
96
cic/actions/deploy.py
Normal file
96
cic/actions/deploy.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# standard imports
|
||||||
|
import logging
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
# external imports
|
||||||
|
from cic_types.ext.metadata import MetadataRequestsHandler
|
||||||
|
from cic_types.ext.metadata.signer import Signer as MetadataSigner
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from cic import (
|
||||||
|
Proof,
|
||||||
|
Processor,
|
||||||
|
)
|
||||||
|
from cic.output import (
|
||||||
|
HTTPWriter,
|
||||||
|
KeyedWriterFactory,
|
||||||
|
)
|
||||||
|
from cic.meta import (
|
||||||
|
Meta,
|
||||||
|
MetadataWriter,
|
||||||
|
)
|
||||||
|
from cic.attachment import Attachment
|
||||||
|
from cic.network import Network
|
||||||
|
from cic.token import Token
|
||||||
|
from typing import Optional
|
||||||
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def init_writers_from_config(config):
|
||||||
|
w = {
|
||||||
|
'meta': None,
|
||||||
|
'attachment': None,
|
||||||
|
'proof': None,
|
||||||
|
'ext': None,
|
||||||
|
}
|
||||||
|
for v in w.keys():
|
||||||
|
k = 'CIC_CORE_{}_WRITER'.format(v.upper())
|
||||||
|
(d, c) = config.get(k).rsplit('.', maxsplit=1)
|
||||||
|
m = importlib.import_module(d)
|
||||||
|
o = getattr(m, c)
|
||||||
|
w[v] = o
|
||||||
|
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def deploy(config, target: str,contract_directory: str, metadata_endpoint: Optional[str], keystore_directory: str, key_file_path: str, gpg_passphrase: str):
|
||||||
|
modname = 'cic.ext.{}'.format(target)
|
||||||
|
cmd_mod = importlib.import_module(modname)
|
||||||
|
|
||||||
|
writers = init_writers_from_config(config)
|
||||||
|
output_directory = os.path.join(contract_directory, 'out')
|
||||||
|
output_writer_path_meta = output_directory
|
||||||
|
if metadata_endpoint != None:
|
||||||
|
MetadataRequestsHandler.base_url = metadata_endpoint
|
||||||
|
MetadataSigner.gpg_path = os.path.join('/tmp')
|
||||||
|
MetadataSigner.key_file_path = key_file_path
|
||||||
|
MetadataSigner.gpg_passphrase = gpg_passphrase
|
||||||
|
writers['proof'] = KeyedWriterFactory(MetadataWriter, HTTPWriter).new
|
||||||
|
writers['attachment'] = KeyedWriterFactory(None, HTTPWriter).new
|
||||||
|
writers['meta'] = MetadataWriter
|
||||||
|
output_writer_path_meta = metadata_endpoint
|
||||||
|
|
||||||
|
ct = Token(path=contract_directory)
|
||||||
|
cm = Meta(path=contract_directory, writer=writers['meta'](path=output_writer_path_meta))
|
||||||
|
ca = Attachment(path=contract_directory, writer=writers['attachment'](path=output_writer_path_meta))
|
||||||
|
cp = Proof(path=contract_directory, attachments=ca, writer=writers['proof'](path=output_writer_path_meta))
|
||||||
|
cn = Network(path=contract_directory)
|
||||||
|
|
||||||
|
ca.load()
|
||||||
|
ct.load()
|
||||||
|
cp.load()
|
||||||
|
cm.load()
|
||||||
|
cn.load()
|
||||||
|
|
||||||
|
chain_spec = None
|
||||||
|
try:
|
||||||
|
chain_spec = config.get('CHAIN_SPEC')
|
||||||
|
except KeyError:
|
||||||
|
chain_spec = cn.chain_spec
|
||||||
|
config.add(chain_spec, 'CHAIN_SPEC', exists_ok=True)
|
||||||
|
logg.debug(f'CHAIN_SPEC config set to {str(chain_spec)}')
|
||||||
|
|
||||||
|
(rpc, signer) = cmd_mod.parse_adapter(config, keystore_directory)
|
||||||
|
|
||||||
|
ref = cn.resource(target)
|
||||||
|
chain_spec = cn.chain_spec(target)
|
||||||
|
logg.debug('found reference {} chain spec {} for target {}'.format(ref['contents'], chain_spec, target))
|
||||||
|
c = getattr(cmd_mod, 'new')(chain_spec, ref['contents'], cp, signer_hint=signer, rpc=rpc, outputs_writer=writers['ext'](path=output_directory))
|
||||||
|
c.apply_token(ct)
|
||||||
|
|
||||||
|
p = Processor(proof=cp, attachment=ca, metadata=cm, extensions=[c])
|
||||||
|
p.process()
|
@ -1,6 +1,6 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from .base import *
|
from .base import *
|
||||||
|
351
cic/cmd/easy.py
Normal file
351
cic/cmd/easy.py
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
# standard import
|
||||||
|
import importlib
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# external imports
|
||||||
|
from chainlib.chain import ChainSpec
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from cic import Proof
|
||||||
|
from cic.actions.deploy import deploy
|
||||||
|
from cic.attachment import Attachment
|
||||||
|
from cic.meta import Meta
|
||||||
|
from cic.network import Network
|
||||||
|
from cic.token import Token
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def process_args(argparser):
|
||||||
|
argparser.add_argument(
|
||||||
|
"--skip-gen", action="store_true", default=False, help="Skip Generation"
|
||||||
|
)
|
||||||
|
argparser.add_argument(
|
||||||
|
"--skip-deploy",
|
||||||
|
action="store_true",
|
||||||
|
help="Skip Deployment",
|
||||||
|
)
|
||||||
|
argparser.add_argument(
|
||||||
|
"--target",
|
||||||
|
default="eth",
|
||||||
|
help="Contract Tech Target (eth)",
|
||||||
|
)
|
||||||
|
argparser.add_argument(
|
||||||
|
"path",
|
||||||
|
type=str,
|
||||||
|
help="Path to generate/use contract deployment info",
|
||||||
|
)
|
||||||
|
argparser.add_argument(
|
||||||
|
"-p",
|
||||||
|
type=str,
|
||||||
|
help="RPC Provider (http://localhost:8545)",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_args(args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
CONTRACTS = [
|
||||||
|
{
|
||||||
|
"url": "https://gitlab.com/cicnet/eth-erc20/-/raw/master/python/giftable_erc20_token/data/GiftableToken",
|
||||||
|
"name": "Giftable Token",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://gitlab.com/cicnet/erc20-demurrage-token/-/raw/master/python/erc20_demurrage_token/data/DemurrageTokenMultiCap",
|
||||||
|
"name": "Demurrage Token Multi Cap (Might not work)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://gitlab.com/cicnet/erc20-demurrage-token/-/raw/master/python/erc20_demurrage_token/data/DemurrageTokenMultiNocap",
|
||||||
|
"name": "Demurrage Token Multi No Cap (Might not work)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://gitlab.com/cicnet/erc20-demurrage-token/-/raw/master/python/erc20_demurrage_token/data/DemurrageTokenSingleCap",
|
||||||
|
"name": "Demurrage Token Single Cap (Might not work)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://gitlab.com/cicnet/erc20-demurrage-token/-/raw/master/python/erc20_demurrage_token/data/DemurrageTokenSingleNocap",
|
||||||
|
"name": "Demurrage Token Single No Cap",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Download File from Url
|
||||||
|
def download_file(url: str, directory: str, filename=None) -> (str, bytes):
|
||||||
|
os.makedirs(directory, exist_ok=True)
|
||||||
|
filename = filename if filename else url.split("/")[-1]
|
||||||
|
path = os.path.join(directory, filename)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
log.debug(f"Downloading {filename}")
|
||||||
|
r = requests.get(url, allow_redirects=True)
|
||||||
|
open(path, "wb").write(r.content)
|
||||||
|
return path
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def get_contract_args(data: list):
|
||||||
|
for item in data:
|
||||||
|
if item["type"] == "constructor":
|
||||||
|
return item["inputs"]
|
||||||
|
raise Exception("No constructor found in contract")
|
||||||
|
|
||||||
|
|
||||||
|
def print_contract_args(json_path: str):
|
||||||
|
json_data = json.load(open(json_path))
|
||||||
|
print(f"Contract Args:")
|
||||||
|
for contract_arg in get_contract_args(json_data):
|
||||||
|
print(
|
||||||
|
f"\t{contract_arg.get('name', '<no name>')} - {contract_arg.get('type', '<no type>')}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def select_contract():
|
||||||
|
print(f"Contracts:")
|
||||||
|
print(f"\t C - Custom (path/url to contract)")
|
||||||
|
for idx, contract in enumerate(CONTRACTS):
|
||||||
|
print(f"\t {idx} - {contract['name']}")
|
||||||
|
|
||||||
|
val = input("Select contract (C,0,1..): ")
|
||||||
|
if val.isdigit() and int(val) < len(CONTRACTS):
|
||||||
|
contract = CONTRACTS[int(val)]
|
||||||
|
directory = f"./contracts/{contract['name']}"
|
||||||
|
bin_path = os.path.abspath(download_file(contract["url"] + ".bin", directory))
|
||||||
|
json_path = download_file(contract["url"] + ".json", directory)
|
||||||
|
elif val == "C":
|
||||||
|
possible_bin_location = input("Enter path/url to contract: ")
|
||||||
|
# possible_bin_location is path
|
||||||
|
if possible_bin_location[0] == "." or possible_bin_location[0] == "/":
|
||||||
|
if os.path.exists(possible_bin_location):
|
||||||
|
bin_path = os.path.abspath(possible_bin_location)
|
||||||
|
else:
|
||||||
|
raise Exception(f"File {possible_bin_location} does not exist")
|
||||||
|
|
||||||
|
possible_json_path = val.replace(".bin", ".json")
|
||||||
|
if os.path.exists(possible_json_path):
|
||||||
|
json_path = possible_json_path
|
||||||
|
# possible_bin_location is url
|
||||||
|
else:
|
||||||
|
bin_path = download_file(contract["url"] + ".bin", directory)
|
||||||
|
else:
|
||||||
|
print("Invalid selection")
|
||||||
|
exit(1)
|
||||||
|
extra_args = []
|
||||||
|
extra_args_types = []
|
||||||
|
|
||||||
|
if os.path.exists(json_path):
|
||||||
|
json_data = json.load(open(json_path))
|
||||||
|
for contract_arg in get_contract_args(json_data):
|
||||||
|
arg_name = contract_arg.get("name")
|
||||||
|
arg_type = contract_arg.get("type")
|
||||||
|
if arg_name not in ["_decimals", "_name", "_symbol"]:
|
||||||
|
val = input(f"Enter value for {arg_name} ({arg_type}): ")
|
||||||
|
extra_args.append(val)
|
||||||
|
extra_args_types.append(arg_type)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"bin_path": bin_path,
|
||||||
|
"json_path": json_path,
|
||||||
|
"extra_args": extra_args,
|
||||||
|
"extra_args_types": extra_args_types,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def init_token(
|
||||||
|
directory: str,
|
||||||
|
code="",
|
||||||
|
extra_args=[],
|
||||||
|
extra_args_types=[],
|
||||||
|
):
|
||||||
|
contract = select_contract()
|
||||||
|
code = contract["bin_path"]
|
||||||
|
extra_args = contract["extra_args"]
|
||||||
|
extra_args_types = contract["extra_args_types"]
|
||||||
|
|
||||||
|
name = input("Enter Token Name (Foo Token): ") or "Foo Token"
|
||||||
|
symbol = input("Enter Token Symbol (FOO): ") or "FOO"
|
||||||
|
precision = input("Enter Token Precision (6): ") or 6
|
||||||
|
supply = input("Enter Token Supply (0): ") or 0
|
||||||
|
|
||||||
|
contract_token = Token(
|
||||||
|
directory,
|
||||||
|
name=name,
|
||||||
|
symbol=symbol,
|
||||||
|
precision=precision,
|
||||||
|
extra_args=extra_args,
|
||||||
|
extra_args_types=extra_args_types,
|
||||||
|
supply=supply,
|
||||||
|
code=code,
|
||||||
|
)
|
||||||
|
contract_token.start()
|
||||||
|
return contract_token
|
||||||
|
|
||||||
|
|
||||||
|
def init_proof(directory):
|
||||||
|
description = input("Enter Proof Description (None): ") or None
|
||||||
|
namespace = input("Enter Proof Namespace (ge): ") or "ge"
|
||||||
|
issuer = input("Enter Proof Issuer (None): ") or None
|
||||||
|
contract_proof = Proof(directory, description, namespace, issuer)
|
||||||
|
contract_proof.start()
|
||||||
|
return contract_proof
|
||||||
|
|
||||||
|
|
||||||
|
def init_meta(directory):
|
||||||
|
name = input("Enter Name (None): ") or ""
|
||||||
|
country_code = input("Enter Country Code (KE): ") or "KE"
|
||||||
|
location = input("Enter Location (None): ") or ""
|
||||||
|
adding_contact_info = True
|
||||||
|
contact = {}
|
||||||
|
while adding_contact_info:
|
||||||
|
value = input("Enter contact info (e.g 'phone: +254723522718'): ") or None
|
||||||
|
if value:
|
||||||
|
data = value.split(":")
|
||||||
|
if len(data) != 2:
|
||||||
|
print("Invalid contact info, you must enter in the format 'key: value'")
|
||||||
|
continue
|
||||||
|
contact[data[0].strip()] = data[1].strip()
|
||||||
|
else:
|
||||||
|
adding_contact_info = False
|
||||||
|
contract_meta = Meta(
|
||||||
|
directory,
|
||||||
|
name=name,
|
||||||
|
country_code=country_code,
|
||||||
|
location=location,
|
||||||
|
contact=contact,
|
||||||
|
)
|
||||||
|
contract_meta.start()
|
||||||
|
return contract_meta
|
||||||
|
|
||||||
|
|
||||||
|
def init_attachment(directory):
|
||||||
|
contract_attchment = Attachment(directory)
|
||||||
|
contract_attchment.start()
|
||||||
|
input(
|
||||||
|
f"Please add attachment files to '{os.path.abspath(os.path.join(directory,'attachments'))}' and then press ENTER to continue"
|
||||||
|
)
|
||||||
|
contract_attchment.load()
|
||||||
|
return contract_attchment
|
||||||
|
|
||||||
|
|
||||||
|
def init_network(
|
||||||
|
directory, registry_address,key_account_address, chain_spec, rpc_provider, targets=["eth"]
|
||||||
|
):
|
||||||
|
contract_network = Network(directory, targets=targets)
|
||||||
|
contract_network.start()
|
||||||
|
|
||||||
|
for target in targets:
|
||||||
|
m = importlib.import_module(f"cic.ext.{target}.start")
|
||||||
|
m.extension_start(
|
||||||
|
contract_network,
|
||||||
|
registry_address=registry_address,
|
||||||
|
chain_spec=chain_spec,
|
||||||
|
rpc_provider=rpc_provider,
|
||||||
|
key_account_address=key_account_address
|
||||||
|
)
|
||||||
|
contract_network.load()
|
||||||
|
return contract_network
|
||||||
|
|
||||||
|
|
||||||
|
def execute(config, eargs):
|
||||||
|
directory = eargs.path
|
||||||
|
if os.path.exists(directory):
|
||||||
|
contine = input(
|
||||||
|
"Directory already exists, Would you like to delete it? (y/n): "
|
||||||
|
)
|
||||||
|
if contine.lower() != "y":
|
||||||
|
print("Exiting")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
print(f"Deleted {directory}")
|
||||||
|
os.system(f"rm -rf {directory}")
|
||||||
|
target = eargs.target
|
||||||
|
if not eargs.skip_gen:
|
||||||
|
os.makedirs(directory)
|
||||||
|
# Defaults
|
||||||
|
default_contract_registry = config.get(
|
||||||
|
"CIC_CONTRACT_REGISTRY_ADDRESS",
|
||||||
|
"0xcf60ebc445b636a5ab787f9e8bc465a2a3ef8299",
|
||||||
|
)
|
||||||
|
default_key_account = config.get(
|
||||||
|
"CIC_KEY_ACCOUNT_ADDRESS", "eb3907ecad74a0013c259d5874ae7f22dcbcc95c"
|
||||||
|
)
|
||||||
|
default_metadata_endpoint = "http://localhost:63380" or config.get(
|
||||||
|
"META_ENDPOINT", "http://localhost:63380"
|
||||||
|
)
|
||||||
|
default_wallet_keyfile = config.get(
|
||||||
|
"WALLET_KEY_FILE",
|
||||||
|
"/home/will/grassroots/cic-internal-integration/apps/cic-ussd/tests/data/pgp/privatekeys_meta.asc",
|
||||||
|
)
|
||||||
|
default_wallet_passphrase = config.get("WALLET_PASSPHRASE", "merman")
|
||||||
|
|
||||||
|
default_chain_spec = config.get("CHAIN_SPEC", "evm:byzantium:8996:bloxberg")
|
||||||
|
default_rpc_provider = config.get("RPC_PROVIDER", "http://localhost:63545")
|
||||||
|
|
||||||
|
# Options
|
||||||
|
contract_registry = (
|
||||||
|
input(f"Enter Contract Registry ({default_contract_registry}): ")
|
||||||
|
or default_contract_registry
|
||||||
|
)
|
||||||
|
rpc_provider = (
|
||||||
|
input(f"Enter RPC Provider ({default_rpc_provider}): ")
|
||||||
|
or default_rpc_provider
|
||||||
|
)
|
||||||
|
chain_spec = ChainSpec.from_chain_str(
|
||||||
|
(input(f"Enter ChainSpec ({default_chain_spec}): ") or default_chain_spec)
|
||||||
|
)
|
||||||
|
key_account = (
|
||||||
|
input(f"Enter KeyAccount ({default_key_account}): ") or default_key_account
|
||||||
|
)
|
||||||
|
metadata_endpoint = (
|
||||||
|
input(f"Enter Metadata Endpoint ({default_metadata_endpoint}): ")
|
||||||
|
or default_metadata_endpoint
|
||||||
|
)
|
||||||
|
|
||||||
|
token = init_token(directory)
|
||||||
|
proof = init_proof(directory)
|
||||||
|
meta = init_meta(directory)
|
||||||
|
attachment = init_attachment(directory)
|
||||||
|
network = init_network(
|
||||||
|
directory,
|
||||||
|
registry_address=contract_registry,
|
||||||
|
key_account_address=key_account,
|
||||||
|
chain_spec=chain_spec,
|
||||||
|
rpc_provider=rpc_provider,
|
||||||
|
targets=[target],
|
||||||
|
)
|
||||||
|
print(f"[cic.header]\nversion = {proof.version()}\n")
|
||||||
|
print(f"[cic.token]\n{token}")
|
||||||
|
print(f"[cic.proof]\n{proof}")
|
||||||
|
print(f"[cic.meta]\n{meta}")
|
||||||
|
print(f"[cic.attachment]\n{attachment}")
|
||||||
|
print(f"[cic.network]\n{network}")
|
||||||
|
if not eargs.skip_deploy:
|
||||||
|
ready_to_deploy = input("Ready to deploy? (y/n): ")
|
||||||
|
if ready_to_deploy == "y":
|
||||||
|
deploy(
|
||||||
|
config,
|
||||||
|
contract_directory=directory,
|
||||||
|
gpg_passphrase=default_wallet_passphrase,
|
||||||
|
key_file_path=default_wallet_keyfile,
|
||||||
|
metadata_endpoint=metadata_endpoint,
|
||||||
|
keystore_directory="/home/will/grassroots/cic-internal-integration/apps/contract-migration/keystore",
|
||||||
|
target=target,
|
||||||
|
)
|
||||||
|
print("Deployed")
|
||||||
|
else:
|
||||||
|
print("Not deploying")
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# rpc="http://localhost:63545"
|
||||||
|
|
||||||
|
# python -m cic.runnable.cic_cmd init --target eth --name "$token_name" --symbol $token_symbol --precision 6 $token_symbol_lowercase
|
||||||
|
|
||||||
|
# python -m cic.runnable.cic_cmd ext -p $rpc -i $chain_spec --registry $contract_registry -d $token_symbol_lowercase eth -vv
|
||||||
|
# python -m cic.runnable.cic_cmd export -p $rpc --metadata-endpoint http://localhost:63380 -vv -y /home/will/grassroots/cic-internal-integration/apps/contract-migration/keystore -o $token_symbol_lowercase/out -d $token_symbol_lowercase eth
|
||||||
|
if __name__ == "__main__":
|
||||||
|
execute()
|
@ -23,7 +23,7 @@ from cic.meta import (
|
|||||||
from cic.attachment import Attachment
|
from cic.attachment import Attachment
|
||||||
from cic.network import Network
|
from cic.network import Network
|
||||||
from cic.token import Token
|
from cic.token import Token
|
||||||
|
from typing import Optional
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -56,8 +56,9 @@ def init_writers_from_config(config):
|
|||||||
|
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
EArgs = {'target': str, 'directory': str, 'output_directory': str, 'metadata_endpoint': Optional[str], 'y': str}
|
||||||
|
|
||||||
def execute(config, eargs):
|
def execute(config, eargs: EArgs):
|
||||||
modname = 'cic.ext.{}'.format(eargs.target)
|
modname = 'cic.ext.{}'.format(eargs.target)
|
||||||
cmd_mod = importlib.import_module(modname)
|
cmd_mod = importlib.import_module(modname)
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ def execute(config, eargs):
|
|||||||
if eargs.metadata_endpoint != None:
|
if eargs.metadata_endpoint != None:
|
||||||
MetadataRequestsHandler.base_url = eargs.metadata_endpoint
|
MetadataRequestsHandler.base_url = eargs.metadata_endpoint
|
||||||
MetadataSigner.gpg_path = os.path.join('/tmp')
|
MetadataSigner.gpg_path = os.path.join('/tmp')
|
||||||
MetadataSigner.key_file_path = '/home/lash/src/client/cic/grassrootseconomics/cic-internal-integration/apps/cic-ussd/tests/data/pgp/privatekeys_meta.asc'
|
MetadataSigner.key_file_path = '/home/will/grassroots/cic-internal-integration/apps/cic-ussd/tests/data/pgp/privatekeys_meta.asc'
|
||||||
MetadataSigner.gpg_passphrase = 'merman'
|
MetadataSigner.gpg_passphrase = 'merman'
|
||||||
writers['proof'] = KeyedWriterFactory(MetadataWriter, HTTPWriter).new
|
writers['proof'] = KeyedWriterFactory(MetadataWriter, HTTPWriter).new
|
||||||
writers['attachment'] = KeyedWriterFactory(None, HTTPWriter).new
|
writers['attachment'] = KeyedWriterFactory(None, HTTPWriter).new
|
||||||
|
@ -25,6 +25,6 @@ def execute(config, eargs):
|
|||||||
|
|
||||||
|
|
||||||
chain_spec = ChainSpec.from_chain_str(eargs.i)
|
chain_spec = ChainSpec.from_chain_str(eargs.i)
|
||||||
m = importlib.import_module('cic.ext.{}.start'.format(eargs.target))
|
m = importlib.import_module(f'cic.ext.{eargs.target}.start')
|
||||||
m.extension_start(cn, registry_address=eargs.registry, chain_spec=chain_spec, rpc_provider=config.get('RPC_PROVIDER'))
|
m.extension_start(cn, registry_address=eargs.registry, chain_spec=chain_spec, rpc_provider=config.get('RPC_PROVIDER'))
|
||||||
|
|
||||||
|
@ -3,3 +3,10 @@ meta_writer = cic.output.KVWriter
|
|||||||
attachment_writer = cic.output.KVWriter
|
attachment_writer = cic.output.KVWriter
|
||||||
proof_writer = cic.output.KVWriter
|
proof_writer = cic.output.KVWriter
|
||||||
ext_writer = cic.output.KVWriter
|
ext_writer = cic.output.KVWriter
|
||||||
|
|
||||||
|
[cic]
|
||||||
|
contract_registry_address =
|
||||||
|
key_account_address =
|
||||||
|
|
||||||
|
[meta]
|
||||||
|
endpoint=https://meta.grassecon.net
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# external imports
|
# external imports
|
||||||
from cic_eth_registry import CICRegistry
|
|
||||||
from chainlib.eth.connection import RPCConnection
|
from chainlib.eth.connection import RPCConnection
|
||||||
|
from cic_eth_registry import CICRegistry
|
||||||
|
|
||||||
|
|
||||||
def extension_start(network, *args, **kwargs):
|
def extension_start(network, *args, **kwargs):
|
||||||
@ -9,18 +9,26 @@ def extension_start(network, *args, **kwargs):
|
|||||||
:param network: Network object to read and write settings from
|
:param network: Network object to read and write settings from
|
||||||
:type network: cic.network.Network
|
:type network: cic.network.Network
|
||||||
"""
|
"""
|
||||||
CICRegistry.address = kwargs['registry_address']
|
CICRegistry.address = kwargs["registry_address"]
|
||||||
|
|
||||||
RPCConnection.register_location(kwargs['rpc_provider'], kwargs['chain_spec'])
|
key_account_address = kwargs["key_account_address"] or ""
|
||||||
conn = RPCConnection.connect(kwargs['chain_spec'])
|
|
||||||
|
|
||||||
registry = CICRegistry(kwargs['chain_spec'], conn)
|
RPCConnection.register_location(kwargs["rpc_provider"], kwargs["chain_spec"])
|
||||||
|
conn = RPCConnection.connect(kwargs["chain_spec"])
|
||||||
|
|
||||||
address_declarator = registry.by_name('AddressDeclarator')
|
registry = CICRegistry(kwargs["chain_spec"], conn)
|
||||||
network.resource_set('eth', 'address_declarator', address_declarator)
|
|
||||||
|
|
||||||
token_index = registry.by_name('TokenRegistry')
|
address_declarator = registry.by_name("AddressDeclarator")
|
||||||
network.resource_set('eth', 'token_index', token_index)
|
network.resource_set(
|
||||||
|
"eth", "address_declarator", address_declarator, key_account=key_account_address
|
||||||
|
)
|
||||||
|
|
||||||
network.set('eth', kwargs['chain_spec'])
|
token_index = registry.by_name("TokenRegistry")
|
||||||
|
network.resource_set(
|
||||||
|
"eth", "token_index", token_index, key_account=key_account_address
|
||||||
|
)
|
||||||
|
|
||||||
|
network.resource_set("eth", "token", None, key_account=key_account_address)
|
||||||
|
|
||||||
|
network.set("eth", kwargs["chain_spec"])
|
||||||
network.save()
|
network.save()
|
||||||
|
42
cic/meta.py
42
cic/meta.py
@ -1,21 +1,20 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import os
|
import base64
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import base64
|
import os
|
||||||
|
|
||||||
# external imports
|
# external imports
|
||||||
from cic_types import MetadataPointer
|
from cic_types import MetadataPointer
|
||||||
from cic_types.processor import generate_metadata_pointer
|
|
||||||
from cic_types.ext.metadata import MetadataRequestsHandler
|
from cic_types.ext.metadata import MetadataRequestsHandler
|
||||||
|
from cic_types.processor import generate_metadata_pointer
|
||||||
from hexathon import strip_0x
|
from hexathon import strip_0x
|
||||||
|
|
||||||
# local imports
|
|
||||||
from .base import (
|
|
||||||
Data,
|
|
||||||
data_dir,
|
|
||||||
)
|
|
||||||
from cic.output import OutputWriter
|
from cic.output import OutputWriter
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from .base import Data, data_dir
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -29,10 +28,12 @@ class Meta(Data):
|
|||||||
:param writer: Writer interface receiving the output of the processor
|
:param writer: Writer interface receiving the output of the processor
|
||||||
:type writer: cic.output.OutputWriter
|
:type writer: cic.output.OutputWriter
|
||||||
"""
|
"""
|
||||||
def __init__(self, path='.', writer=None):
|
def __init__(self, path='.', writer=None, name="", location="", country_code="", contact={}):
|
||||||
super(Meta, self).__init__()
|
super(Meta, self).__init__()
|
||||||
self.name = None
|
self.name = None
|
||||||
self.contact = {}
|
self.contact = contact
|
||||||
|
self.country_code = country_code
|
||||||
|
self.location = location
|
||||||
self.path = path
|
self.path = path
|
||||||
self.writer = writer
|
self.writer = writer
|
||||||
self.meta_path = os.path.join(self.path, 'meta.json')
|
self.meta_path = os.path.join(self.path, 'meta.json')
|
||||||
@ -49,7 +50,8 @@ class Meta(Data):
|
|||||||
|
|
||||||
self.name = o['name']
|
self.name = o['name']
|
||||||
self.contact = o['contact']
|
self.contact = o['contact']
|
||||||
|
self.country_code = o['country_code']
|
||||||
|
self.location = o['location']
|
||||||
self.inited = True
|
self.inited = True
|
||||||
|
|
||||||
|
|
||||||
@ -64,6 +66,11 @@ class Meta(Data):
|
|||||||
o = json.load(f)
|
o = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
o['name'] = self.name
|
||||||
|
o['contact'] = self.contact
|
||||||
|
o['country_code'] = self.country_code
|
||||||
|
o['location'] = self.location
|
||||||
|
|
||||||
f = open(self.meta_path, 'w')
|
f = open(self.meta_path, 'w')
|
||||||
json.dump(o, f, sort_keys=True, indent="\t")
|
json.dump(o, f, sort_keys=True, indent="\t")
|
||||||
f.close()
|
f.close()
|
||||||
@ -107,12 +114,15 @@ class Meta(Data):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = "contact.name = {}\n".format(self.name)
|
s = f"contact.name = {self.name}\n"
|
||||||
|
s = f"contact.country_code = {self.country_code}\n"
|
||||||
for k in self.contact.keys():
|
s = f"contact.location = {self.location}\n"
|
||||||
if self.contact[k] == '':
|
for contact_key in self.contact.keys():
|
||||||
|
contact_value = self.contact[contact_key]
|
||||||
|
if not contact_value:
|
||||||
|
s += f"contact.{contact_key} = \n"
|
||||||
continue
|
continue
|
||||||
s += "contact.{} = {}\n".format(k.lower(), self.contact[k])
|
s += f"contact.{contact_key} = {contact_value}\n"
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class Network(Data):
|
|||||||
"""
|
"""
|
||||||
super(Network, self).load()
|
super(Network, self).load()
|
||||||
|
|
||||||
network_template_file_path = os.path.join(data_dir, 'network_template_v{}.json'.format(self.version()))
|
network_template_file_path = os.path.join(data_dir, f'network_template_v{self.version()}.json')
|
||||||
|
|
||||||
f = open(network_template_file_path)
|
f = open(network_template_file_path)
|
||||||
o_part = json.load(f)
|
o_part = json.load(f)
|
||||||
@ -138,11 +138,11 @@ class Network(Data):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = ''
|
s = ''
|
||||||
for k in self.resources.keys():
|
for resource in self.resources.keys():
|
||||||
for kk in self.resources[k]['contents'].keys():
|
for content_key in self.resources[resource]['contents'].keys():
|
||||||
v = self.resources[k]['contents'][kk]
|
content_value = self.resources[resource]['contents'][content_key]
|
||||||
if v == None:
|
if content_value == None:
|
||||||
v = ''
|
content_value = ''
|
||||||
s += '{}.{} = {}\n'.format(k, kk, v)
|
s += f'{resource}.{content_key} = {content_value}\n'
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
82
cic/proof.py
82
cic/proof.py
@ -33,34 +33,40 @@ class Proof(Data):
|
|||||||
:type writer: cic.output.OutputWriter
|
:type writer: cic.output.OutputWriter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, path='.', attachments=None, writer=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
path=".",
|
||||||
|
description=None,
|
||||||
|
namespace="ge",
|
||||||
|
issuer=None,
|
||||||
|
attachments=None,
|
||||||
|
writer=None,
|
||||||
|
):
|
||||||
super(Proof, self).__init__()
|
super(Proof, self).__init__()
|
||||||
self.proofs = []
|
self.proofs = []
|
||||||
self.namespace = 'ge'
|
self.namespace = namespace
|
||||||
self.description = None
|
self.description = description
|
||||||
self.issuer = None
|
self.issuer = issuer
|
||||||
self.path = path
|
self.path = path
|
||||||
self.writer = writer
|
self.writer = writer
|
||||||
self.extra_attachments = attachments
|
self.extra_attachments = attachments
|
||||||
self.attachments = {}
|
self.attachments = {}
|
||||||
self.proof_path = os.path.join(self.path, 'proof.json')
|
self.proof_path = os.path.join(self.path, "proof.json")
|
||||||
self.temp_proof_path = tempfile.mkstemp()[1]
|
self.temp_proof_path = tempfile.mkstemp()[1]
|
||||||
|
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""Load proof data from settings.
|
"""Load proof data from settings."""
|
||||||
"""
|
|
||||||
super(Proof, self).load()
|
super(Proof, self).load()
|
||||||
|
|
||||||
f = open(self.proof_path, 'r')
|
f = open(self.proof_path, "r")
|
||||||
o = json.load(f)
|
o = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
self.set_version(o['version'])
|
self.set_version(o["version"])
|
||||||
self.description = o['description']
|
self.description = o["description"]
|
||||||
self.namespace = o['namespace']
|
self.namespace = o["namespace"]
|
||||||
self.issuer = o['issuer']
|
self.issuer = o["issuer"]
|
||||||
self.proofs = o['proofs']
|
self.proofs = o["proofs"]
|
||||||
|
|
||||||
if self.extra_attachments != None:
|
if self.extra_attachments != None:
|
||||||
a = self.extra_attachments.asdict()
|
a = self.extra_attachments.asdict()
|
||||||
@ -72,35 +78,34 @@ class Proof(Data):
|
|||||||
|
|
||||||
self.inited = True
|
self.inited = True
|
||||||
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Initialize proof settings from template.
|
"""Initialize proof settings from template."""
|
||||||
"""
|
|
||||||
super(Proof, self).start()
|
super(Proof, self).start()
|
||||||
|
|
||||||
proof_template_file_path = os.path.join(data_dir, 'proof_template_v{}.json'.format(self.version()))
|
proof_template_file_path = os.path.join(
|
||||||
|
data_dir, "proof_template_v{}.json".format(self.version())
|
||||||
|
)
|
||||||
|
|
||||||
f = open(proof_template_file_path)
|
f = open(proof_template_file_path)
|
||||||
o = json.load(f)
|
o = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
o["issuer"] = self.issuer
|
||||||
f = open(self.proof_path, 'w')
|
o["description"] = self.description
|
||||||
|
o["namespace"] = self.namespace
|
||||||
|
f = open(self.proof_path, "w")
|
||||||
json.dump(o, f, sort_keys=True, indent="\t")
|
json.dump(o, f, sort_keys=True, indent="\t")
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def asdict(self):
|
def asdict(self):
|
||||||
"""Output proof state to dict.
|
"""Output proof state to dict."""
|
||||||
"""
|
|
||||||
return {
|
return {
|
||||||
'version': self.version(),
|
"version": self.version(),
|
||||||
'namespace': self.namespace,
|
"namespace": self.namespace,
|
||||||
'description': self.description,
|
"description": self.description,
|
||||||
'issuer': self.issuer,
|
"issuer": self.issuer,
|
||||||
'proofs': self.proofs,
|
"proofs": self.proofs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# TODO: the efficiency of this method could probably be improved.
|
# TODO: the efficiency of this method could probably be improved.
|
||||||
def __get_ordered_hashes(self):
|
def __get_ordered_hashes(self):
|
||||||
ks = list(self.attachments.keys())
|
ks = list(self.attachments.keys())
|
||||||
@ -108,30 +113,26 @@ class Proof(Data):
|
|||||||
|
|
||||||
return ks
|
return ks
|
||||||
|
|
||||||
|
|
||||||
# def get(self):
|
# def get(self):
|
||||||
# hsh = self.hash(b).hex()
|
# hsh = self.hash(b).hex()
|
||||||
# self.attachments[hsh] = self.temp_proof_path
|
# self.attachments[hsh] = self.temp_proof_path
|
||||||
# logg.debug('cbor of {} is {} hashes to {}'.format(v, b.hex(), hsh))
|
# logg.debug('cbor of {} is {} hashes to {}'.format(v, b.hex(), hsh))
|
||||||
|
|
||||||
|
|
||||||
def root(self):
|
def root(self):
|
||||||
"""Calculate the root digest from the serialized proof object.
|
"""Calculate the root digest from the serialized proof object."""
|
||||||
"""
|
|
||||||
v = self.asdict()
|
v = self.asdict()
|
||||||
# b = cbor2.dumps(v)
|
# b = cbor2.dumps(v)
|
||||||
b = json.dumps(v)
|
b = json.dumps(v)
|
||||||
|
|
||||||
f = open(self.temp_proof_path, 'w')
|
f = open(self.temp_proof_path, "w")
|
||||||
f.write(b)
|
f.write(b)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
b = b.encode('utf-8')
|
b = b.encode("utf-8")
|
||||||
k = self.hash(b)
|
k = self.hash(b)
|
||||||
|
|
||||||
return (k.hex(), b)
|
return (k.hex(), b)
|
||||||
|
|
||||||
|
|
||||||
def process(self, token_address=None, token_symbol=None, writer=None):
|
def process(self, token_address=None, token_symbol=None, writer=None):
|
||||||
"""Serialize and publish proof.
|
"""Serialize and publish proof.
|
||||||
|
|
||||||
@ -144,8 +145,10 @@ class Proof(Data):
|
|||||||
writer.write(k, v)
|
writer.write(k, v)
|
||||||
root_key = k
|
root_key = k
|
||||||
|
|
||||||
token_symbol_bytes = token_symbol.encode('utf-8')
|
token_symbol_bytes = token_symbol.encode("utf-8")
|
||||||
k = generate_metadata_pointer(token_symbol_bytes, MetadataPointer.TOKEN_PROOF_SYMBOL)
|
k = generate_metadata_pointer(
|
||||||
|
token_symbol_bytes, MetadataPointer.TOKEN_PROOF_SYMBOL
|
||||||
|
)
|
||||||
writer.write(k, v)
|
writer.write(k, v)
|
||||||
|
|
||||||
token_address_bytes = bytes.fromhex(strip_0x(token_address))
|
token_address_bytes = bytes.fromhex(strip_0x(token_address))
|
||||||
@ -170,12 +173,11 @@ class Proof(Data):
|
|||||||
# writer.write(r_hex, hshs_cat)
|
# writer.write(r_hex, hshs_cat)
|
||||||
|
|
||||||
o = self.asdict()
|
o = self.asdict()
|
||||||
f = open(self.proof_path, 'w')
|
f = open(self.proof_path, "w")
|
||||||
json.dump(o, f, sort_keys=True, indent="\t")
|
json.dump(o, f, sort_keys=True, indent="\t")
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
return root_key
|
return root_key
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "description = {}\n".format(self.description)
|
return "description = {}\n".format(self.description)
|
||||||
|
@ -11,6 +11,7 @@ import cic.cmd.init as cmd_init
|
|||||||
import cic.cmd.show as cmd_show
|
import cic.cmd.show as cmd_show
|
||||||
import cic.cmd.ext as cmd_ext
|
import cic.cmd.ext as cmd_ext
|
||||||
import cic.cmd.export as cmd_export
|
import cic.cmd.export as cmd_export
|
||||||
|
import cic.cmd.easy as cmd_easy
|
||||||
|
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
@ -34,6 +35,8 @@ cmd_export.process_args(sub_export)
|
|||||||
sub_ext = sub.add_parser('ext', help='extension helpers')
|
sub_ext = sub.add_parser('ext', help='extension helpers')
|
||||||
cmd_ext.process_args(sub_ext)
|
cmd_ext.process_args(sub_ext)
|
||||||
|
|
||||||
|
sub_easy = sub.add_parser('easy', help='Easy Mode Contract Deployment')
|
||||||
|
cmd_easy.process_args(sub_easy)
|
||||||
|
|
||||||
args = argparser.parse_args(sys.argv[1:])
|
args = argparser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
82
cic/token.py
82
cic/token.py
@ -1,12 +1,9 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from .base import (
|
from .base import Data, data_dir
|
||||||
Data,
|
|
||||||
data_dir,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Token(Data):
|
class Token(Data):
|
||||||
@ -27,40 +24,49 @@ class Token(Data):
|
|||||||
:param code: Bytecode for token chain application
|
:param code: Bytecode for token chain application
|
||||||
:type code: str (hex)
|
:type code: str (hex)
|
||||||
"""
|
"""
|
||||||
def __init__(self, path='.', name=None, symbol=None, precision=1, supply=0, code=None):
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
path=".",
|
||||||
|
name=None,
|
||||||
|
symbol=None,
|
||||||
|
precision=1,
|
||||||
|
supply=0,
|
||||||
|
code=None,
|
||||||
|
extra_args=[],
|
||||||
|
extra_args_types=[],
|
||||||
|
):
|
||||||
super(Token, self).__init__()
|
super(Token, self).__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.symbol = symbol
|
self.symbol = symbol
|
||||||
self.supply = supply
|
self.supply = supply
|
||||||
self.precision = precision
|
self.precision = precision
|
||||||
self.code = code
|
self.code = code
|
||||||
self.extra_args: list = []
|
self.extra_args = extra_args
|
||||||
self.extra_args_types: list = []
|
self.extra_args_types = extra_args_types
|
||||||
self.path = path
|
self.path = path
|
||||||
self.token_path = os.path.join(self.path, 'token.json')
|
self.token_path = os.path.join(self.path, "token.json")
|
||||||
|
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""Load token data from settings.
|
"""Load token data from settings."""
|
||||||
"""
|
|
||||||
super(Token, self).load()
|
super(Token, self).load()
|
||||||
|
|
||||||
f = open(self.token_path, 'r')
|
f = open(self.token_path, "r")
|
||||||
o = json.load(f)
|
o = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
self.name = o['name']
|
self.name = o["name"]
|
||||||
self.symbol = o['symbol']
|
self.symbol = o["symbol"]
|
||||||
self.precision = o['precision']
|
self.precision = o["precision"]
|
||||||
self.code = o['code']
|
self.code = o["code"]
|
||||||
self.supply = o['supply']
|
self.supply = o["supply"]
|
||||||
extras = []
|
extras = []
|
||||||
extra_types = []
|
extra_types = []
|
||||||
token_extras: list = o['extra']
|
token_extras: list = o["extra"]
|
||||||
if token_extras:
|
if token_extras:
|
||||||
for token_extra in token_extras:
|
for token_extra in token_extras:
|
||||||
arg = token_extra.get('arg')
|
arg = token_extra.get("arg")
|
||||||
arg_type = token_extra.get('arg_type')
|
arg_type = token_extra.get("arg_type")
|
||||||
if arg:
|
if arg:
|
||||||
extras.append(arg)
|
extras.append(arg)
|
||||||
if arg_type:
|
if arg_type:
|
||||||
@ -69,32 +75,40 @@ class Token(Data):
|
|||||||
self.extra_args_types = extra_types
|
self.extra_args_types = extra_types
|
||||||
self.inited = True
|
self.inited = True
|
||||||
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Initialize token settings from arguments passed to the constructor and/or template.
|
"""Initialize token settings from arguments passed to the constructor and/or template."""
|
||||||
"""
|
|
||||||
super(Token, self).load()
|
super(Token, self).load()
|
||||||
|
|
||||||
token_template_file_path = os.path.join(data_dir, 'token_template_v{}.json'.format(self.version()))
|
token_template_file_path = os.path.join(
|
||||||
|
data_dir, "token_template_v{}.json".format(self.version())
|
||||||
|
)
|
||||||
|
|
||||||
f = open(token_template_file_path)
|
f = open(token_template_file_path)
|
||||||
o = json.load(f)
|
o = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
|
o["name"] = self.name
|
||||||
|
o["symbol"] = self.symbol
|
||||||
|
o["precision"] = self.precision
|
||||||
|
o["code"] = self.code
|
||||||
|
o["supply"] = self.supply
|
||||||
|
extra = []
|
||||||
|
for i in range(len(self.extra_args)):
|
||||||
|
extra.append(
|
||||||
|
{"arg": self.extra_args[i], "arg_type": self.extra_args_types[i]}
|
||||||
|
)
|
||||||
|
if len(extra):
|
||||||
|
o["extra"] = extra
|
||||||
|
print(extra)
|
||||||
|
|
||||||
o['name'] = self.name
|
f = open(self.token_path, "w")
|
||||||
o['symbol'] = self.symbol
|
|
||||||
o['precision'] = self.precision
|
|
||||||
o['code'] = self.code
|
|
||||||
o['supply'] = self.supply
|
|
||||||
|
|
||||||
f = open(self.token_path, 'w')
|
|
||||||
json.dump(o, f, sort_keys=True, indent="\t")
|
json.dump(o, f, sort_keys=True, indent="\t")
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = """name = {}
|
s = """name = {}
|
||||||
symbol = {}
|
symbol = {}
|
||||||
precision = {}
|
precision = {}
|
||||||
""".format(self.name, self.symbol, self.precision)
|
""".format(
|
||||||
|
self.name, self.symbol, self.precision
|
||||||
|
)
|
||||||
return s
|
return s
|
||||||
|
@ -3,3 +3,4 @@ cic-types~=0.2.1a5
|
|||||||
confini~=0.5.1
|
confini~=0.5.1
|
||||||
chainlib~=0.0.13
|
chainlib~=0.0.13
|
||||||
cbor2==5.4.1
|
cbor2==5.4.1
|
||||||
|
click==8.0.3
|
Loading…
Reference in New Issue
Block a user