Skip to main content
info

For Cadence 0.42 go to Legacy Docs

Flow SDK Convert

The FlowSDK provides a Convert class to convert between Cadence and C# datatypes. It provides two functions, ToCadence and FromCadence.

The conversion is strict in regards to the types of the data. C# types must match the Cadence type being converted from/to or an exception will be thrown. The following are the required types:

CadenceC#
IntBigInteger
UIntBigInteger
Int8SByte
Int16Int16
Int32Int32
Int64Int64
Int128BigInteger
Int256BigInteger
UInt8Byte
UInt16UInt16
UInt32UInt32
UInt64UInt64
UInt128BigInteger
UInt256BigInteger
Word8Byte
Word16UInt16
Word32UInt32
Word64UInt64
Fix64Decimal
UFix64Decimal
AddressString
StringString
BoolBoolean
PathCadencePathValue
CapabilityCadenceCapabilityValue
Array ([T])List<T>
Dictionary ({T:R})Dictionary<T,R>
StructClass or Struct

Usage​

ToCadence​

The Convert.ToCadence function has the following signature:


_10
public static CadenceBase ToCadence(object source, string destinationType)

ToCadence will return a CadenceBase that can be passed into Script and Transaction functions. Example:


_10
CadenceBase cb = Convert.ToCadence((Int64)44, "Int64");

This will result in a CadenceNumber with a value of "44" and a type of "Int64". However:


_10
CadenceBase cb = Convert.ToCadence(44, "Int64");

will result in an exception "Exception: Can not convert System.Int32 into Int64. Requires source to be System.Int64."

Similarly, the Cadence Int type is an arbitrary precision integer type and thus must be created using a System.BigInteger.


_10
CadenceBase cb = Convert.ToCadence(new BigInteger(44), "Int");

FromCadence​

The Convert.FromCadence has the following signature:


_10
public static T FromCadence<T>(CadenceBase cadence)

where T is the C# you would like the Cadence converted into.

FromCadence will return a value of the requested type given a CadenceBase value. The Cadence and C# types must match.


_10
CadenceBase cb = new CadenceNumber(CadenceNumberType.Int16, "44");
_10
Int16 i = Convert.FromCadence<Int16>(cb);

If the requested and source types do not match, an exception will be thrown.


_10
CadenceBase cb = new CadenceNumber(CadenceNumberType.Int16, "44");
_10
Int64 i = Convert.FromCadence<Int64>(cb);

The above results in an exception: "Exception: Attempt to convert cadence to invalid type. Cadence type Int16 expects System.Int16, got System.Int64".

Composite Types​

Using the Convert class on primitive types isn't much easier than constructing the Cadence types yourself. Using it on Composite types is much more useful.

Convert can convert between Cadence composite types (Struct, Enum, Resource, Event, Contract) and C# structs/classes. In order to annotate your C# classes/structs a CadenceAttribute is provided. The CadenceAttribute has two properties. The Name and CadenceType properties allow you to provide hints to the converter as to what each C# types should be when converted to Cadence.

Given the following C# class:


_10
public class TestStruct
_10
{
_10
public Int32 i32;
_10
public String s;
_10
}

and the following Cadence struct:


_10
access(all) struct TestStruct {
_10
access(all) let i32: Int32
_10
access(all) let s: String
_10
}

you can convert from Cadence to C# using:


_10
TestStruct ts = Convert.FromCadence<TestStruct>(cadence);

It will match based on the field names, and the types are compatible. Converting from C# to Cadence, on the other hand, requires annotations.


_10
[Cadence(CadenceType="A.XXX.CCC.TestStruct")]
_10
public class TestStruct
_10
{
_10
[Cadence(CadenceType="Int32", Name="i32")]
_10
public Int32 i;
_10
[Cadence(CadenceType="String")]
_10
public String s;
_10
}

This is because a C# string could be a Cadence Address or Cadence String. For consistency, Convert requires all C#->Cadence conversions to be annotated with a CadenceType. If a field is not annotated, it will be skipped when converting from C# to Cadence.

You can also use the Name parameter to account for differences in field naming. In the above example we mapped the Cadence "i32" field to the C# "i" field. The Name property is optional and it will use the field name if no Name property is given.

Note: The CadenceType annotation on C# classes/structs ([Cadence(CadenceType="A.XXX.CCC.TestStruct")] in the above example) is ignored when converting from Cadence to C#. Convert.FromCadence will populate all fields that have matching names/types regardless of the type of Cadence struct that is being converted. This allows you to convert a Cadence struct defined int a Cadence script into C# even if you do not know what the Cadence type is.

The class annotation (A.XXX.CCC.TestStruct) is required when converting from C# to Cadence. XXX should be the address of the account that contains the contract where the struct is defined, without a leading "0x". The CCC is the name of the contract.

Here's an example using the NBA TopShot contract (https://github.com/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShot.cdc) on TestNet, defining a class to hold the Play struct:


_10
[Cadence(CadenceType="A.877931736ee77cff.TopShot.Play")]
_10
public class Play
_10
{
_10
[Cadence(CadenceType="UInt32")]
_10
public UInt32 playID;
_10
[Cadence(CadenceType="{String:String}")]
_10
public Dictionary<String, String> metadata;
_10
}

Structs inside Structs​

If a Cadence struct contains another struct, the field should be annotated as a "Struct". Given the following Cadence:


_15
access(all) struct Other {
_15
access(all) let i: Int16
_15
_15
access(all) init(i:Int16) {
_15
self.i=i
_15
}
_15
}
_15
_15
access(all) struct Test {
_15
access(all) let o : Other
_15
_15
access(all) init(i: Int16) {
_15
self.o = Other(i:i)
_15
}
_15
}

you could use this C#:


_13
[Cadence(CadenceType="A.xxx.ccc.Nested")]
_13
public class Other
_13
{
_13
[Cadence(CadenceType="Int16")]
_13
public Int16 i;
_13
}
_13
_13
[Cadence(CadenceType="A.xxx.ccc.Test")]
_13
public class Test
_13
{
_13
[Cadence(CadenceType="Struct")]
_13
public Other o;
_13
}

If you have a Cadence Test struct you can convert into C# using:


_10
TestStruct ts = Convert.FromCadence<TestStruct>(cadence);

If you have a C# Test object, you can convert to Cadence using:


_10
CadenceBase cb = Convert.ToCadence(ts, "Struct");

Optionals​

Cadence optionals are indicated by appending a ?. For instance the Cadence type Int16? can contain either an Int16 value or nil. If the C# type is a reference type, no additional work is required. For instance a Cadence String? will have the C# equivalent type of String. This is because the C# String is a reference type, which can natively be set to null. On the other hand, the Cadence Int16? requires the C# type Int16? which wraps type the value type Int16 in a Nullable<>.


_10
//c is a Cadence Int16? type
_10
Int16? i = Convert.FromCadence<Int16?>(c);

Trying to convert a Cadence optional into a non-nullable type results in an exception:


_10
//c is a Cadence Int16? type
_10
Int16 i = Convert.FromCadence<Int16>(c);

"Exception: CadenceOptional requires a nullable type"