2

I have two contracts contract_one and contract_two. On contract_two I have an on-chain-view defined like this:

@sp.onchain_view()
def get(self, id):
    sp.result(self.data.map[id])

This view works correctly. Now what I want is to call this view from contract_one. Here's what I've tried:

@sp.onchain_view()
def get(self, id):
    contract_address = sp.local("contract_address", sp.address('CONTRACT_ONE_ADDRESS'))
    result = sp.local("result", sp.view("get", contract_address.value, id, t = sp.TRecord( data = sp.TString, address = sp.TAddress )).open_some("Invalid view"))
    sp.result(result.value)

Although the contract is compiled successfully, I cannot originate it to hangzhounet, getting the following error:

 "Http error response: (400) Failed to parse the request body: No case matched:\n...

The error then lists several /kind reasons.

My question is, what I'm trying to do, is it possible to achieve? Is there another way to do this? My final goal is to call this view with Taquito and get a result.

2
  • 1
    What you want to do is very possible. Your problem is unrelated. Also, you should take advantage of SmartPy tests before going to test networks.
    – FFF
    Commented Mar 23, 2022 at 17:11
  • @FFF So do I use a combination of on-chain views or something else like Lamda views for example?
    – user8188
    Commented Mar 23, 2022 at 19:59

2 Answers 2

1

Not too familiar with SmartPy, but this is exactly what onchain views are supposed to do, so it should work. My best guess (again, I'm a ligo developer and have very little knowledge of SmartPy), is that the @sp.onchain_view() decorator in contract_one should be replaced by @sp.entry_point, as the get function in contract_one is an entrypoint calling an onchain view, and not a view function. See this example of calling an onchain view in the smartpy docs: https://smartpy.io/docs/general/views/#examples-1

5
  • Thanks for the answer. I am probably missing something, but aren't entry points supposed to have no returns? Meaning that it cannot return an object?
    – user8188
    Commented Mar 23, 2022 at 15:10
  • 1
    I guess I misunderstood your intention. Yes. Entrypoints don't have a return, they only make changes to the contract's storage and send out operations. Onchain views do have a return, but a view has access only to the storage of the contract it lives in, and isn't supposed to be able to call another contract's view. It is strange to me that this even compiled... Commented Mar 23, 2022 at 15:32
  • > It is strange to me that this even compiled... Probably nobody tried this :)
    – user8188
    Commented Mar 23, 2022 at 15:45
  • Well. I didn't think this was supposed to be possible to do, but I've reproduced and deployed: better-call.dev/hangzhou2net/… Commented Mar 24, 2022 at 0:56
  • @AharonLando you can indeed call on-chain views from on-chain views
    – 0x10
    Commented Apr 30, 2022 at 6:35
1

Yes, you can create it. Here is a small working example of what you are trying to do.

import smartpy as sp


class contract_two(sp.Contract):
    def __init__(self):
        self.init(
            _map = sp.map({
                0: sp.record(
                    data = 'data',
                    address = sp.address('tz1burnburnburnburnburnburnburjAYjjX')
                )
            })
        )

    @sp.onchain_view()
    def get(self, id):
        sp.result(self.data._map[id])


class contract_one(sp.Contract):
    def __init__(self, contract_two_address):
        self.init(
            contract_two_address = contract_two_address
        )

    @sp.onchain_view()
    def get(self, id):
        result = sp.view(
            "get",
            self.data.contract_two_address,
            id,
            t = sp.TRecord( data = sp.TString, address = sp.TAddress )
        ).open_some("Invalid view")
        sp.result(result)


@sp.add_test(name = 'Test')
def test():
    scenario = sp.test_scenario()
    admin = sp.test_account('admin')

    c2 = contract_two()
    scenario += c2
    c1 = contract_one(c2.address)
    scenario += c1

    result = c1.get(0)
    scenario.show(result)

Few things to note:

  • Use _map instead of map, because it conflicts with Python's methods.
  • When you are deploying the contract_one, make sure to write a valid contract address instead of CONTRACT_ONE_ADDRESS
  • And, that contract should have this on-chain view you're trying to call.
  • I can't conclude the exact cause of the /kind error because I'll need the complete log for that.
  • No need to define local variables (at least in the example that you've given).
  • If you face difficulty calling it with Taquito, raise a separate question. Will try to help with Taquito there :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.