diff --git a/tests/all_tests_v2.nim b/tests/all_tests_v2.nim index a4cdaa379..0acf3892a 100644 --- a/tests/all_tests_v2.nim +++ b/tests/all_tests_v2.nim @@ -7,7 +7,7 @@ import ./v2/test_waku_filter, ./v2/test_waku_pagination, ./v2/test_waku_payload, - ./v2/test_waku_swap, +# ./v2/test_waku_swap, ./v2/test_message_store, ./v2/test_jsonrpc_waku, ./v2/test_peer_manager, diff --git a/tests/v2/test_waku_swap_contracts.nim b/tests/v2/test_waku_swap_contracts.nim index b95947094..29a27203e 100644 --- a/tests/v2/test_waku_swap_contracts.nim +++ b/tests/v2/test_waku_swap_contracts.nim @@ -2,7 +2,9 @@ # import std/[unittest, options, tables, sets, osproc, strutils, strformat, json], - ../test_helpers, ./utils + chronicles, + ../test_helpers, ./utils, + ../../waku/v2/protocol/waku_swap/waku_swap_contracts procSuite "Basic balance test": var aliceSwapAddress = "" @@ -10,93 +12,51 @@ procSuite "Basic balance test": var erc20address = "" test "Get pwd of swap module": let (output, errC) = osproc.execCmdEx("(cd ../swap-contracts-module && pwd)") - echo output + debug "output", output check: contains(output, "swap-contracts-module") test "Get balance from running node": # NOTE: This corresponds to the first default account in Hardhat - let taskString = "npx hardhat --network localhost balance --account 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - let cmdString = "cd ../swap-contracts-module; " & &"{taskString}" - echo cmdString - let (output, errC) = osproc.execCmdEx(cmdString) - echo output + let balance = waku_swap_contracts.getBalance("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") check: - contains(output, "ETH") + contains(balance, "ETH") test "Setup Swap": - let taskString = "npx hardhat --network localhost setupSwap" - let cmdString = "cd ../swap-contracts-module; " & &"{taskString}" - echo cmdString - let (output, errC) = osproc.execCmdEx(cmdString) + let json = waku_swap_contracts.setupSwap() - # XXX Assume succeeds - let json = parseJson(output) var aliceAddress = json["aliceAddress"].getStr() aliceSwapAddress = json["aliceSwapAddress"].getStr() erc20address = json["erc20address"].getStr() - echo erc20address - echo json + debug "erc20address", erc20address + debug "json", json # Contains default Alice account check: contains(aliceAddress, "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") test "Sign Cheque": - #npx hardhat signCheque --swapaddress "0x94099942864EA81cCF197E9D71ac53310b1468D8" - let taskString = "npx hardhat --network localhost signCheque --swapaddress '" & &"{aliceSwapAddress}" & "'" - let cmdString = "cd ../swap-contracts-module; " & &"{taskString}" - echo cmdString - let (output, errC) = osproc.execCmdEx(cmdString) + signature = waku_swap_contracts.signCheque(aliceSwapAddress) - # XXX Assume succeeds - let json = parseJson(output) - signature = json["signature"].getStr() - echo json - echo signature - - # Contains some signature check: contains(signature, "0x") - test "Get balances 1": - let taskString = "npx hardhat --network localhost getBalances --erc20address '" & &"{erc20address}" & "'" - let cmdString = "cd ../swap-contracts-module; " & &"{taskString}" - echo cmdString - let (output, errC) = osproc.execCmdEx(cmdString) + test "Get ERC20 Balances": + let json = getERC20Balances(erc20address) - # XXX Assume succeeds - let json = parseJson(output) - echo json - - # Contains some signature check: - contains(signature, "0x") + json["bobBalance"].getInt() == 10000 test "Redeem cheque and check balance": - # XXX Simplify string creation - let taskString = "npx hardhat --network localhost redeemCheque --swapaddress '" & &"{aliceSwapAddress}" & "' --signature '" & &"{signature}" & "'" - let cmdString = "cd ../swap-contracts-module; " & &"{taskString}" - echo cmdString - let (output, errC) = osproc.execCmdEx(cmdString) - - # XXX Assume succeeds - echo output - let json = parseJson(output) + let json = waku_swap_contracts.redeemCheque(aliceSwapAddress, signature) var resp = json["resp"].getStr() - echo json + debug "json", json - echo "Get balances" - let taskString2 = "npx hardhat --network localhost getBalances --erc20address '" & &"{erc20address}" & "'" - let cmdString2 = "cd ../swap-contracts-module; " & &"{taskString2}" - echo cmdString2 - let (output2, errC2) = osproc.execCmdEx(cmdString2) - - # XXX Assume succeeds - let json2 = parseJson(output2) - echo json2 + debug "Get balances" + let json2 = getERC20Balances(erc20address) + debug "json", json2 # Balance for Bob has now increased check: diff --git a/waku/v2/protocol/waku_swap/waku_swap.nim b/waku/v2/protocol/waku_swap/waku_swap.nim index 7ec827d71..83854adb5 100644 --- a/waku/v2/protocol/waku_swap/waku_swap.nim +++ b/waku/v2/protocol/waku_swap/waku_swap.nim @@ -31,7 +31,8 @@ import libp2p/stream/connection, ../../node/peer_manager, ../message_notifier, - ./waku_swap_types + ./waku_swap_types, + ../../waku/v2/protocol/waku_swap/waku_swap_contracts export waku_swap_types @@ -59,6 +60,7 @@ proc encode*(cheque: Cheque): ProtoBuffer = result.write(1, cheque.beneficiary) result.write(2, cheque.date) result.write(3, cheque.amount) + result.write(4, cheque.signature) proc init*(T: type Handshake, buffer: seq[byte]): ProtoResult[T] = var beneficiary: seq[byte] @@ -73,12 +75,14 @@ proc init*(T: type Cheque, buffer: seq[byte]): ProtoResult[T] = var beneficiary: seq[byte] var date: uint32 var amount: uint32 + var signature: seq[byte] var cheque = Cheque() let pb = initProtoBuffer(buffer) discard ? pb.getField(1, cheque.beneficiary) discard ? pb.getField(2, cheque.date) discard ? pb.getField(3, cheque.amount) + discard ? pb.getField(4, cheque.signature) ok(cheque) @@ -89,6 +93,8 @@ proc init*(T: type Cheque, buffer: seq[byte]): ProtoResult[T] = # TODO Test for credit/debit operations in succession + +# TODO Assume we calculated cheque proc sendCheque*(ws: WakuSwap) {.async.} = let peerOpt = ws.peerManager.selectPeer(WakuSwapCodec) @@ -109,9 +115,14 @@ proc sendCheque*(ws: WakuSwap) {.async.} = info "sendCheque" + # TODO We get this from the setup of swap setup, dynamic, should be part of setup # TODO Add beneficiary, etc - # XXX Hardcoded amount for now - await connOpt.get().writeLP(Cheque(amount: 1).encode().buffer) + var aliceSwapAddress = "0x6C3d502f1a97d4470b881015b83D9Dd1062172e1" + let signature = waku_swap_contracts.signCheque(aliceSwapAddress) + info "Signed Cheque", swapAddress = aliceSwapAddress, signature = signature + + let sigBytes = cast[seq[byte]](signature) + await connOpt.get().writeLP(Cheque(amount: 1, signature: sigBytes).encode().buffer) # Set new balance let peerId = peer.peerId @@ -119,6 +130,7 @@ proc sendCheque*(ws: WakuSwap) {.async.} = info "New accounting state", accounting = ws.accounting[peerId] # TODO Authenticate cheque, check beneficiary etc +# TODO Redeem cheque proc handleCheque*(ws: WakuSwap, cheque: Cheque) = info "handle incoming cheque" # XXX Assume peerId is first peer @@ -169,6 +181,7 @@ proc init*(wakuSwap: WakuSwap) = # TODO Isolate to policy function # TODO Tunable payment threshhold, hard code for PoC + # XXX: Where should this happen? Apply policy... let paymentThreshhold = 1 if wakuSwap.accounting[peerId] >= paymentThreshhold: info "Payment threshhold hit, send cheque" diff --git a/waku/v2/protocol/waku_swap/waku_swap_contracts.nim b/waku/v2/protocol/waku_swap/waku_swap_contracts.nim new file mode 100644 index 000000000..87c3b101c --- /dev/null +++ b/waku/v2/protocol/waku_swap/waku_swap_contracts.nim @@ -0,0 +1,65 @@ +# Glue code to interact with SWAP contracts module. +# +# Assumes swap-contracts-module node is running. +# +import + std/[osproc, strutils, json], + chronicles + +logScope: + topics = "wakuswapcontracts" + +# XXX In general this is not a good API, more a collection of hacky glue code for PoC. +# +# TODO Error handling + +# Interacts with node in sibling path and interacts with a local Hardhat node. +const taskPrelude = "npx hardhat --network localhost " +const cmdPrelude = "cd ../swap-contracts-module; " & taskPrelude + +proc execNodeTask(taskStr: string): tuple[output: TaintedString, exitCode: int] = + let cmdString = $cmdPrelude & $taskStr + debug "execNodeTask", cmdString + return osproc.execCmdEx(cmdString) + +# TODO JSON? +proc getBalance*(accountAddress: string): string = + let task = "balance --account " & $accountAddress + let (output, errC) = execNodeTask(task) + debug "getBalance", output + return output + +proc setupSwap*(): JsonNode = + let task = "setupSwap" + let (output, errC) = execNodeTask(task) + + # XXX Assume succeeds + let json = parseJson(output) + return json + +# TODO Signature +proc signCheque*(swapAddress: string): string = + let task = "signCheque --swapaddress '" & $swapAddress & "'" + let (output, errC) = execNodeTask(task) + + # XXX Assume succeeds + let json = parseJson(output) + let signature = json["signature"].getStr() + debug "signCheque", json=json, signature=signature + return signature + +proc getERC20Balances*(erc20address: string): JsonNode = + let task = "getBalances --erc20address '" & $erc20address & "'" + let (output, errC) = execNodeTask(task) + + # XXX Assume succeeds + let json = parseJson(output) + return json + +proc redeemCheque*(swapAddress: string, signature: string): JsonNode = + let task = "redeemCheque --swapaddress '" & $swapAddress & "' --signature '" & $signature & "'" + let (output, errC) = execNodeTask(task) + + # XXX Assume succeeds + let json = parseJson(output) + return json diff --git a/waku/v2/protocol/waku_swap/waku_swap_types.nim b/waku/v2/protocol/waku_swap/waku_swap_types.nim index 09ce46c9c..25d44d3b7 100644 --- a/waku/v2/protocol/waku_swap/waku_swap_types.nim +++ b/waku/v2/protocol/waku_swap/waku_swap_types.nim @@ -12,10 +12,13 @@ type Handshake* = object beneficiary*: Beneficiary + # XXX I'm confused by lack of signature here, most important thing... + # TODO Look over these data structures again Cheque* = object beneficiary*: Beneficiary date*: uint32 amount*: uint32 + signature*: seq[byte] CreditHandler* = proc (peerId: PeerId, amount: int) {.gcsafe, closure.} DebitHandler* = proc (peerId: PeerId, amount: int) {.gcsafe, closure.}