1

I am translating following code in solidity to smartpy. How do we achieve a variable type of struct in smartPy.

        Types.AssetTransferDetail[]
            memory _assetDetails = new Types.AssetTransferDetail[](
                _coinNames.length
            );
        for (uint256 i = 0; i < _coinNames.length; i++) {
            _assets[i] = Types.Asset(_coinNames[i], _values[i]);
            _assetDetails[i] = Types.AssetTransferDetail(
                _coinNames[i],
                _values[i],
                _fees[i]
            );
        }

These structs are defined in Types.sol library.

struct Asset {
        string coinName;
        uint256 value;
    }

   struct AssetTransferDetail {
        string coinName;
        uint256 value;
        uint256 fee;
    }

1 Answer 1

1

In SmartPy it corresponds to records.

With the new syntax:

import smartpy as sp

@sp.module
def main():
    Asset: type = sp.record(
        coinName=sp.string,
        value=sp.nat,
    )
    AssetTransferDetail: type = sp.record(
        coinName=sp.string,
        value=sp.nat,
        fee=sp.mutez,
    )
    
    class MyContract(sp.Contract):
        def __init__(self, coinNames, values, fees):
            self.data.assets = sp.cast(sp.big_map(), sp.big_map[sp.nat, Asset])
            self.data.assetDetails = sp.cast(sp.big_map(), sp.big_map[sp.nat, AssetTransferDetail])
            for i in coinNames.keys():
                self.data.assets[i] = sp.record(
                    coinName=coinNames[i],
                    value=values[i],
                )
                self.data.assetDetails[i] = sp.record(
                    coinName=coinNames[i],
                    value=values[i],
                    fee=fees[i]
                )

        @sp.entrypoint
        def ep(self):
            pass


if "templates" not in __name__:
    @sp.add_test(name="MyContract")
    def test():
        sc = sp.test_scenario(main)
        c1 = main.MyContract(
            {0: "MyCoin"}, {0: 0}, {0: sp.mutez(5)}
        )
        sc += c1
        c1.ep()

With the legacy syntax:

import smartpy as sp

Asset = sp.TRecord(
    coinName=sp.TString,
    value=sp.TNat,
)
AssetTransferDetail = sp.TRecord(
    coinName=sp.TString,
    value=sp.TNat,
    fee=sp.TMutez,
)

class MyContract(sp.Contract):
    def __init__(self, coinNames, values, fees):
        assets = {}
        assetDetails = {}
        for i in range(len(coinNames)):
            assets[i] = sp.record(
                coinName=coinNames[i],
                value=values[i],
            )
            assetDetails[i] = sp.record(
                coinName=coinNames[i],
                value=values[i],
                fee=fees[i]
            )

        self.init(
            assets=sp.big_map(assets, tkey=sp.TNat, tvalue=Asset),
            assetDetails=sp.big_map(assetDetails, tkey=sp.TNat, tvalue=AssetTransferDetail),
        )

    @sp.entry_point
    def ep(self):
        pass


if "templates" not in __name__:
    @sp.add_test(name="MyContract")
    def test():
        sc = sp.test_scenario()
        c1 = MyContract(
            ["MyCoin"], [0], [sp.mutez(5)]
        )
        sc += c1
        c1.ep()

Something to notice: on Tezos the constructor is never pushed onchain. With the legacy syntax what you can and cannot do inside the init is different from what you cna do in an entrypoint. If you want the same logic inside an entrypoint you have to make to changes: instead of giving three lists you may prefer give one, you'll have to use sp.if instead of if.

Mind you, this translation is an example. It's not necessarily the best way to create this contract or something that I would approve for production.

5
  • Got it . What would you recommend for the production though
    – theBatMan
    Feb 23 at 6:24
  • And can you recommend it in old version of smartpy.
    – theBatMan
    Feb 23 at 10:42
  • I updated my answer. Can you mark it as resolving your problem if that's the case? I don't know what I would do differently for production except perhaps use python's naming convention: asset_details. Simply notice that I haven't studied your problem in detail so you have to adapt it.
    – Jordan_tez
    Feb 24 at 6:51
  • I am writing above logic in entry_point. And following line coinName=coinNames[i], gives a error: [error] Type Error (params.coin_names : sp.TList(sp.TString)) ( line 207) cannot get item (i : sp.TNat) (, line 120) A list is not a map.
    – theBatMan
    Feb 27 at 9:13
  • Please open a new issue for that.
    – Jordan_tez
    Mar 1 at 9:36

Your Answer

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

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