[contracts] Make contract interactions optional in the node (#91)

Adds --eth-deployment parameter.
Does not crash when deployment json is missing or incorrect.
This commit is contained in:
markspanbroek 2022-04-25 17:12:37 +04:00 committed by GitHub
parent c93e015e43
commit d8ed4257df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 20 deletions

View File

@ -154,6 +154,12 @@ type
name: "eth-account" name: "eth-account"
.}: EthAddress .}: EthAddress
ethDeployment* {.
desc: "The json file describing the contract deployment"
defaultValue: string.default
name: "eth-deployment"
.}: string
of initNode: of initNode:
discard discard

View File

@ -16,5 +16,11 @@ proc deployment*(file = defaultFile): Deployment =
Deployment(json: parseFile(file)) Deployment(json: parseFile(file))
proc address*(deployment: Deployment, Contract: typedesc): ?Address = proc address*(deployment: Deployment, Contract: typedesc): ?Address =
let address = deployment.json["contracts"][$Contract]["address"].getStr() if deployment.json == nil:
Address.init(address) return none Address
try:
let address = deployment.json["contracts"][$Contract]["address"].getStr()
Address.init(address)
except KeyError:
none Address

View File

@ -1,4 +1,5 @@
import pkg/ethers import pkg/ethers
import pkg/chronicles
import ../purchasing import ../purchasing
import ../sales import ../sales
import ../proving import ../proving
@ -10,6 +11,7 @@ import ./proofs
export purchasing export purchasing
export sales export sales
export proving export proving
export chronicles
type type
ContractInteractions* = ref object ContractInteractions* = ref object
@ -19,11 +21,16 @@ type
proc new*(_: type ContractInteractions, proc new*(_: type ContractInteractions,
signer: Signer, signer: Signer,
deployment: Deployment): ContractInteractions = deployment: Deployment): ?ContractInteractions =
let contract = Storage.new(!deployment.address(Storage), signer)
without address =? deployment.address(Storage):
error "Unable to determine address of the Storage smart contract"
return none ContractInteractions
let contract = Storage.new(address, signer)
let market = OnChainMarket.new(contract) let market = OnChainMarket.new(contract)
let proofs = OnChainProofs.new(contract) let proofs = OnChainProofs.new(contract)
ContractInteractions( some ContractInteractions(
purchasing: Purchasing.new(market), purchasing: Purchasing.new(market),
sales: Sales.new(market), sales: Sales.new(market),
proving: Proving.new(proofs) proving: Proving.new(proofs)
@ -31,16 +38,30 @@ proc new*(_: type ContractInteractions,
proc new*(_: type ContractInteractions, proc new*(_: type ContractInteractions,
providerUrl: string, providerUrl: string,
account = Address.default): ContractInteractions = deploymentFile: string = string.default,
account = Address.default): ?ContractInteractions =
let provider = JsonRpcProvider.new(providerUrl) let provider = JsonRpcProvider.new(providerUrl)
var signer: Signer var signer: Signer
if account == Address.default: if account == Address.default:
signer = provider.getSigner() signer = provider.getSigner()
else: else:
signer = provider.getSigner(account) signer = provider.getSigner(account)
ContractInteractions.new(signer, deployment())
proc new*(_: type ContractInteractions): ContractInteractions = var deploy: Deployment
try:
if deploymentFile == string.default:
deploy = deployment()
else:
deploy = deployment(deploymentFile)
except IOError as e:
error "Unable to read deployment json", msg = e.msg
return none ContractInteractions
ContractInteractions.new(signer, deploy)
proc new*(_: type ContractInteractions): ?ContractInteractions =
ContractInteractions.new("ws://localhost:8545") ContractInteractions.new("ws://localhost:8545")
proc start*(interactions: ContractInteractions) {.async.} = proc start*(interactions: ContractInteractions) {.async.} =

View File

@ -122,7 +122,11 @@ proc new*(T: type DaggerServer, config: DaggerConf): T =
engine = BlockExcEngine.new(localStore, wallet, network, discovery) engine = BlockExcEngine.new(localStore, wallet, network, discovery)
store = NetworkStore.new(engine, localStore) store = NetworkStore.new(engine, localStore)
erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider) erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider)
contracts = ContractInteractions.new(config.ethProvider, config.ethAccount) contracts = ContractInteractions.new(
config.ethProvider,
config.ethDeployment,
config.ethAccount
)
daggerNode = DaggerNodeRef.new(switch, store, engine, erasure, discovery, contracts) daggerNode = DaggerNodeRef.new(switch, store, engine, erasure, discovery, contracts)
restServer = RestServerRef.new( restServer = RestServerRef.new(
daggerNode.initRestApi(), daggerNode.initRestApi(),

View File

@ -43,7 +43,7 @@ type
engine*: BlockExcEngine engine*: BlockExcEngine
erasure*: Erasure erasure*: Erasure
discovery*: Discovery discovery*: Discovery
contracts*: ContractInteractions contracts*: ?ContractInteractions
proc start*(node: DaggerNodeRef) {.async.} = proc start*(node: DaggerNodeRef) {.async.} =
await node.switch.start() await node.switch.start()
@ -51,8 +51,8 @@ proc start*(node: DaggerNodeRef) {.async.} =
await node.erasure.start() await node.erasure.start()
await node.discovery.start() await node.discovery.start()
if not node.contracts.isNil: if contracts =? node.contracts:
await node.contracts.start() await contracts.start()
node.networkId = node.switch.peerInfo.peerId node.networkId = node.switch.peerInfo.peerId
notice "Started dagger node", id = $node.networkId, addrs = node.switch.peerInfo.addrs notice "Started dagger node", id = $node.networkId, addrs = node.switch.peerInfo.addrs
@ -65,8 +65,8 @@ proc stop*(node: DaggerNodeRef) {.async.} =
await node.erasure.stop() await node.erasure.stop()
await node.discovery.stop() await node.discovery.stop()
if not node.contracts.isNil: if contracts =? node.contracts:
await node.contracts.stop() await contracts.stop()
proc findPeer*( proc findPeer*(
node: DaggerNodeRef, node: DaggerNodeRef,
@ -244,7 +244,7 @@ proc new*(
engine: BlockExcEngine, engine: BlockExcEngine,
erasure: Erasure, erasure: Erasure,
discovery: Discovery, discovery: Discovery,
contracts: ContractInteractions): T = contracts: ?ContractInteractions): T =
T( T(
switch: switch, switch: switch,
blockStore: store, blockStore: store,

View File

@ -1,3 +1,4 @@
import std/os
import ./ethertest import ./ethertest
import dagger/contracts import dagger/contracts
import ./examples import ./examples
@ -7,18 +8,20 @@ ethersuite "Storage Contract Interactions":
var contracts: ContractInteractions var contracts: ContractInteractions
setup: setup:
contracts = ContractInteractions.new() contracts = !ContractInteractions.new()
test "can be instantiated with a signer and deployment info": test "can be instantiated with a signer and deployment info":
let signer = provider.getSigner() let signer = provider.getSigner()
let deployment = deployment() let deployment = deployment()
check ContractInteractions.new(signer, deployment) != nil check ContractInteractions.new(signer, deployment).isSome
test "can be instantiated with a provider url and account": test "can be instantiated with a provider url and account":
let url = "http://localhost:8545" let url = "http://localhost:8545"
let account = Address.example let account = Address.example
check ContractInteractions.new(url) != nil let deployment = "vendor" / "dagger-contracts" / "deployment-localhost.json"
check ContractInteractions.new(url, account) != nil check ContractInteractions.new(url).isSome
check ContractInteractions.new(url, account = account).isSome
check ContractInteractions.new(url, deploymentFile = deployment).isSome
test "provides purchasing": test "provides purchasing":
check contracts.purchasing != nil check contracts.purchasing != nil

View File

@ -36,7 +36,7 @@ suite "Test Node":
store: NetworkStore store: NetworkStore
node: DaggerNodeRef node: DaggerNodeRef
discovery: Discovery discovery: Discovery
contracts: ContractInteractions contracts: ?ContractInteractions
setup: setup:
file = open(path.splitFile().dir /../ "fixtures" / "test.jpg") file = open(path.splitFile().dir /../ "fixtures" / "test.jpg")