typemove

# TypeMove Generate TypeScript bindings for Iota contracts. ## Features - Code generation for Iota smart contract based on ABI - Typesafe encode/decoding, object filtering, transaction building, etc - Automatically manage depended modules - BCS schema (WIP) ## Usage ### Install package ```shell yarn add @typemove/iota ``` or ```shell pnpm add @typemove/iota ``` ### Code Generation ```typescript yarn typemove-iota [--target-dir] [--network] [--abi-dir] ``` - `location`: Directory of ABI json files or address of account to generate types for - `target-dir`: Directory to output generated files (default: "./types") - `network`: Network to use, could be either "mainnet", "testnet" or any node URL (default: "mainnet") - `abi-dir`: Directory to store downloaded ABI. Only useful if is address (default: "./abis") Use `yarn typemove-iota --help` to see detail description. A few examples: - generate types for an address on mainnet: ```typescript yarn typemove-iota --target-dir=./src/types --abi-dir=./src/abis 0x1e2b124f746a339b3cf99b9f969393a96594519aafb1d06517aacfeeae20e7a5 ``` - generate types for local ABI files stored in `./src/abis`: ```typescript yarn typemove-iota --target-dir=./src/types ./src/abis ``` - generate types using local node: ```typescript yarn typemove-iota --network="http://localhost:8080" 0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af ``` ### Decode Object ```typescript import { defaultMoveCoder } from '@typemove/iota' import { single_collateral } from './types/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.js' const res = await defaultMoveCoder().decodeType( data, single_collateral.Info.type() ) ```
Click to see what's like without TypeMove ```typescript export interface Info { index: string; creator: string; createTsMs: string; round: string; deliveryInfo?: DeliveryInfo; } export interface DeliveryInfo { round: string; price: string; size: string; premium: string; tsMs: string; } let deliveryInfo: DeliveryInfo | undefined = // @ts-ignore data.content.fields.info.fields.delivery_info ? { // @ts-ignore round: data.content.fields.info.fields.delivery_info.fields.round, // @ts-ignore price: data.content.fields.info.fields.delivery_info.fields.price, // @ts-ignore size: data.content.fields.info.fields.delivery_info.fields.size, // @ts-ignore premium: data.content.fields.info.fields.delivery_info.fields.premium, // @ts-ignore tsMs: data.content.fields.info.fields.delivery_info.fields.ts_ms, } : undefined; let info: Info = { // @ts-ignore index: data.content.fields.info.fields.index, // @ts-ignore creator: data.content.fields.info.fields.creator, // @ts-ignore createTsMs: data.content.fields.info.fields.create_ts_ms, // @ts-ignore round: data.content.fields.info.fields.round, deliveryInfo, }; ```
### Decode dynamic fields Get objects with specified type from a list of dynamic objects, and access field with fully typed object ```typescript const decodedObjects = await coder.getDynamicFields( objects, BUILTIN_TYPES.U64_TYPE, single_collateral.PortfolioVault.type() ) console.log(decodedObjects[0].value.info.delivery_info?.price) ``` IDE could infer result type correctly. ![dynamic_fields.png](../../images/dynamic_fields.png) ### View Function With type move, you could, call view functions and get decoded result very easily, e.g. ```typescript import { _0x2 } from '@typemove/iota/builtin' res = (await _0x2.math.view.min(client, [20n, 4n])) console.log(res?.results_decoded[0]) ``` Typemove's generated view function stubs wraps the `devInspectTransactionBlock` API and decode the result, it adds an fully typed `results_decoded` field to the result object. e.g. the above `min` function generated has type annotation as below: ```typescript module math { export async function min( client: IotaClient, args: [bigint | TransactionArgument, bigint | TransactionArgument], ): Promise> { ... } } ``` ### Building transaction Similar to original transaction building process, but you could use generated builder function to replace the `txb.moveCall`. ```typescript import { clob_v2 } from './types/testnet/0xdee9.js' const client = new IotaClient({ url: getFullnodeUrl('testnet') }) const tx = new TransactionBlock() clob_v2.builder.createAccount(tx, ["0xd9e6dc1e7f0790c18acf96b629f0a236d56de2f96537d921197bcb0e071b12bd"]) ... more tx build client.signAndExecuteTransactionBlock({transactionBlock: tx, signer: keypair}) ``` Checkout our [tests](./src/tests/move-call.test.ts) for more examples.