tutorial
Himalia 用于与链的合约部分交互的sdk,需要首先启动一个节点才能进行后续的执行过程。
对于有pallet-contracts
功能的节点,我们推荐使用 Europa 作为节点的替代。更多的信息请参阅Europa的文档。
Europa 可以以一下命令简单安装使用:
git install --recurse-submodules https://github.com/patractlabs/europa.git --force --lockedeuropa --tmp
另一方面也可以使用 Patract 的测试网 Jupiter,或者 Parity 提供的合约测试网 Canvas-node
#
goPatractGo 依赖于 GSRPC。Go 版本的 Himalia 项目叫做 go-patract
在安装了 PatractGo 之后,可以采用如下方式快速部署,调用一个合约。完整案例请参考 transfer_test
#
部署合约// read the code wasm from filecodeBytes, err := ioutil.ReadFile("/path/to/contracts.wasm")if err != nil { return err}// create the apicApi, err := rpc.NewContractAPI(env.URL())
// read the abi(metadata) for contractmetaBz, err := ioutil.ReadFile("/path/to/contracts_metadata.json")cApi.WithMetaData(metaBz)
// create context with from auth, like Alicectx := api.NewCtx(context.Background()).WithFrom(authKey)
// put code_, err = cApi.Native().PutCode(ctx, codeBytes)
codeHash := readCodeHash() // get code hash
var codeBz []byte
if err := cApi.Native().Cli.GetStorageLatest(&codeBz, "Contracts", "PristineCode", []byte(codeHash), nil); err != nil { return err }
var endowment uint64 = 1000000000000
// Instantiate_, contractAccount, err := cApi.Instantiate(ctx, types.NewCompactBalance(endowment), types.NewCompactGas(test.DefaultGas), contracts.CodeHashERC20, types.NewU128(totalSupply),)
#
调用合约#
rpc call调用 total_supply
获取当前的总共供应量。
var res types.U128
err := a.CallToRead(ctx, &res, a.ContractAccountID, []string{"total_supply"},)
#
交易调用调用 transfer
转移一笔资金。
toParam := struct { Address AccountID}{ Address: to,}
valueParam := struct { Value U128}{ Value: amt,}
return a.CallToExec(ctx, a.ContractAccountID, types.NewCompactBalance(0), types.NewCompactGas(test.DefaultGas), []string{"transfer"}, toParam, valueParam,)
#
pythonPatractPy 依赖于 py-substrate-interfacePython 版本的 Himalia 项目叫做 py-patract
#
安装pip3 install -U patract-interface
在 python 脚本中即可使用
from patractinterface import ContractFactory, ContractAPI
// ... So something ...
#
快速使用import osfrom substrateinterface import SubstrateInterface, Keypairfrom patractinterface.contract import ContractAPI, ContractFactoryfrom patractinterface.observer import ContractObserver
def main(): # use [europa](https://github.com/patractlabs/europa) as test node endpoint, notice `type_registry` should set correctly. substrate=SubstrateInterface(url='ws://127.0.0.1:9944', type_registry_preset="default", type_registry={'types': {'LookupSource': 'MultiAddress'}}) # load deployer key alice = Keypair.create_from_uri('//Alice') bob = Keypair.create_from_uri('//Bob') # 1. load a contract from Wasm file and metadata.json file (Those files is complied by [ink!](https://github.com/paritytech/ink)) # in this example, we use `ink/example/erc20` contract as example. contract = ContractFactory.create_from_file( substrate=substrate, # should provide a subtrate endpoint code_file= os.path.join(os.path.dirname(__file__), 'res', 'erc20.wasm'), metadata_file= os.path.join(os.path.dirname(__file__), 'res', 'erc20.json') ) # upload code to chain directly res = contract.put_code(alice) print("update code hash{} res:{}".format(contract.code_hash.hex(), res.is_succes)) # 2. instantiate the uploaded code as a contract instance erc20_ins = contract.new(alice, 1000000 * (10 ** 15), endowment=2*10**10, gas_limit=20000000000, deployment_salt="0x12") # 2.1 create a observer to listen event observer = ContractObserver(erc20_ins.contract_address, erc20_ins.metadata, substrate) # 3. send a transfer call for this contract res = erc20_ins.transfer(alice, bob.ss58_address, 100000, gas_limit=20000000000) print('transfer res', res.is_succes)
def on_transfer(num, evt): print("on_transfer in {} : {} {} {}".format(num, evt['from'], evt['to'], evt['value']))
def on_approval(num, evt): print("on_approval in {} : {} {} {}".format(num, evt['owner'], evt['spender'], evt['value'])) # 4 set event callback observer.scanEvents(handlers={ 'Transfer': on_transfer, 'Approve': on_approval })
if __name__ == "__main__": main() pass