AptoORM is a utility for Object–relational mapping from Typescript and Javascript class objects to Aptos Object model.
Once you define a class in your source code with AptoORM decorators, you can record the class objects to Aptos Blockchain. It is also supported to update, delete them on chain and to transfer the ownership of the objects to others as like other digital assets.
Furthermore, AptoORM can be a framework to create, mint NFT on Aptos Blockchain with simple and clear settings.
- Add
OrmObjecttoOrmClassdecorator. - Add
OrmTokentoOrmTokenClassdecorator. - Add ORM Token generation to
gen-move.ts. - Remove
OrmToken's name, description and uri from user data. - Add OrmToken's name, description and uri fields update procedure with
token_mutable_by_creatorandtoken_mutable_by_owneroptions. - Rename
OrmCollectiontoOrmTokenClass. - Add update and delete operations for
OrmToken. - Add an option,
immutable, for thename,urianddescriptionfields ofOrmToken. - Updated
getfunction generated by user-defined class. - Add Aptos Collection object name option to
OrmTokenConfig. - Add
constantoption toOrmTokenConfigfor fixedname,urianddescriptionfields ofOrmToken. The OrmToken has the same name, uri and descriptions if it is configured. - Add
index_fieldsoption toOrmClassandOrmFieldin order to Aptos create named object. - Add
packageconfiguration - Add default
royalty_payeeto class object. - Add
OrmFreePrepayClient,OrmFreePostpayClientfor free transaction fee interface. - Add
PoAtypescript API - Add
create_to(create and send an object) API - Add
royalty_present_per_tokento represent the royalty to each token. - Add
UpdateDateField(),CreateDateField(). - Add new
OrmFieldoption (token_property) to add/delete the field from/to token's property_map. - Add txn result parser to get the object or token created.
- Add Indexer function to list the created objects.
- Check need to add the move ability [key, store, drop, copy] should be controlled by the AptoORM.
- Add CLIs for example.
Install the npm package:
npm install apto_orm --saveYou need to install reflect-metadata:
npm install reflect-metadata --saveand import it somewhere in the global place of your app (for example in app.ts):
import "reflect-metadata"You may need to install node typings:
npm install @types/node ts-node --save-dev
ts-nodeis required to execute theapto_orm cli.
Also, make sure you are using TypeScript version 4.5 or higher, and you have enabled the following settings in tsconfig.json:
"emitDecoratorMetadata": true,
"experimentalDecorators": true,You can start a project with apto_orm from scratch. Try the following.
# package.json
pnpm init
# add build command to package.json
jq --arg key "build" --arg val "tsc --build" '.scripts[$key]=$val' package.json\
| jq "." > _package.json && mv _package.json package.json
# add `apto_orm` command to package.json
jq --arg key "orm" --arg val "apto_orm" '.scripts[$key]=$val' package.json \
| jq "." > _package.json && mv _package.json package.json
# setup tsconfig
{
echo "{"
echo ' "compilerOptions": {'
echo ' "target": "ES2020",'
echo ' "module": "CommonJS",'
echo ' "moduleResolution": "node",'
echo ' "skipLibCheck": true,'
echo ' "resolveJsonModule": true,'
echo ' "esModuleInterop": true,'
echo ' "emitDecoratorMetadata": true,'
echo ' "experimentalDecorators": true,'
echo ' "allowSyntheticDefaultImports": true,'
echo ' "declaration": false,'
echo ' "outDir": "dist"'
echo ' },'
echo ' "include": ["src"],'
echo ' "exclude": ["node_modules", "**/*.spec.ts"]'
echo "}"
} > tsconfig.json
# setup .gitignore.
{
echo 'dist'
echo 'out'
echo 'build'
echo 'node_modules'
echo '**/build'
echo '.key'
} > .gitignore# Create a keypair to .key directory
mkdir -p .key
aptos key generate --assume-yes --output-file .key/villain
# Initialize Aptos account and receive funds of Aptos Coin
# if devnet or testnet because your package publishing costs Aptos Coin.
aptos init --network devnet --private-key-file .key/villain --profile villainCreate your sample typescript class by apto_orm init command.
This command will create a class file (MyToken.ts) to src/my_tokens.
npx apto_orm init src/my_tokens --key .key/villain --token -c MyTokenModify the following token class to suit your taste.
import { OrmTokenClass, OrmField, OrmIndexField } from 'apto_orm';
@OrmTokenClass({
package_address: '0x43ded2bab6265e70d3fe47879e2af7d7826984c1f44e5fe6cb4912678c3cab40',
package_creator: '0x8953be30cc7c69682a2aa972fefee8d8ba474eb69830349d03cda73f5568e8ff',
package_name: 'my_tokens',
collection_name: 'AptoORM MyToken',
collection_uri: 'https://raw.githubusercontent.com/neoul/apto_orm/main/resource.png',
collection_description: 'Sample AptoORM Token',
max_supply: 1000n,
token_use_property_map: false,
royalty_present: false,
royalty_denominator: 100,
royalty_numerator: 1,
})
export class MyToken {
@OrmIndexField({ immutable: true })
id!: number;
@OrmField({ immutable: true })
name!: string;
@OrmField()
uri!: string;
@OrmField()
description!: string;
}The following command generates a Move module based on your class to
YOUR_PACKAGE_PATH/move.
npx apto_orm generate src/my_tokens
# classes 'MyToken' are created to the package 'my_tokens'
# - creator: 0x8953be30cc7c69682a2aa972fefee8d8ba474eb69830349d03cda73f5568e8ff
# - address: 0x43ded2bab6265e70d3fe47879e2af7d7826984c1f44e5fe6cb4912678c3cab40
# - path: /home/willing/projects/apto_example/src/my_tokensThe generated module must be compiled and published to your package account.
This package account is an object that has the signer capability of your package
and is a place where your package bytecodes are stored.
npx apto_orm compile src/my_tokens
npx apto_orm publish src/my_tokens --key .key/villainPlease check for information about Aptos Move language.
npx apto_orm create src/my_tokens --key .key/villain -c MyToken \
-d '{ "uri": "https://raw.githubusercontent.com/neoul/apto_orm/main/resource.png", "description": "ok", "id": 1, "name": "ABC" }'
npx apto_orm create src/my_tokens --key .key/villain \
--to 0xfd2984f201abdbf30ccd0ec5c2f2357789222c0bbd3c68999acfebe188fdc09d -c MyToken \
-d '{ "uri": "https://raw.githubusercontent.com/neoul/apto_orm/main/resource.png", "description": "ok", "id": 2, "name": "EFG" }'
npx apto_orm delete src/my_tokens --key .key/villain -c MyToken \
-a 0x10dd8012f4c83a2e058347d7178d81432fcadf30cc11e623e2c8ba93a0a786dfOrmClass decorates a Typescript class to declare Aptos Object that the Object model allows Move to represent a complex type as a set of resources stored within a single address.
@OrmClass({
package_creator: '0xabc',
package_name: 'Move package name',
deletable_by_owner: true,
...
})export type OrmObjectConfig = {
/** The creator address of the object and package */
package_creator: AptosAccount | MaybeHexString;
/** The package name where the objects belongs to */
package_name: string;
package_address?: MaybeHexString; // address of the package
/** Aptos creates named objects with predictable hash addresses, which are derived
* from user input and the creator's address. This enables named objects to be indexed
* and traced based on the user input provided by the creator.
* AptoORM facilitates the creation of indexable objects by utilizing `index_fields`
* to organize the fields used in the named object creation.
* Conversely, if index_fields is not set, OrmObject is created with a random address. */
index_fields?: string[];
/** Objects created by the class can be transferred by `object::transfer()`. */
direct_transfer?: boolean;
/** The creator (The owner of OrmCreator object) can remove the ORM objects. */
deletable_by_creator?: boolean;
/** The owner can remove the ORM objects */
deletable_by_owner?: boolean;
/** The creator can transfer the ORM objects by AptoORM facilities. */
indirect_transfer_by_creator?: boolean;
/** The owner can transfer the ORM objects by AptoORM facilities. */
indirect_transfer_by_owner?: boolean;
/** The creator can extend the ORM objects. */
extensible_by_creator?: boolean;
/** The owner can extend the ORM objects. */
extensible_by_owner?: boolean;
named_addresses?: NamedAddresses;
/** The token configuration must be set if the OrmObject is Aptos Token object. */
token_config?: OrmTokenConfig;
};OrmTokenClass is used to define custom Aptos Token Object. The OrmTokenClass should be defined with the OrmObjectConfig and additional following attributes.
/** ORM Token configuration */
export type OrmTokenConfig = {
/** The representative name of the token collection (= Aptos Collection Name) */
collection_name: string;
/** The representative URI of the token collection (= Aptos Collection URI) */
collection_uri: string;
/** The representative description of the token collection (= Aptos Collection Description) */
collection_description: string;
/** The maximum token supply of the AptoORM class (= Aptos Collection Max Supply) */
max_supply: number | bigint;
/** Whether the token uses property map */
token_use_property_map: boolean;
/** Whether the token has royalty or the collection has royalty itself. */
royalty_present: boolean;
/** The payee of the royalty */
royalty_payee: MaybeHexString | string;
/** The denominator of the royalty */
royalty_denominator: number;
/** The numerator of the royalty */
royalty_numerator: number;
};OrmField and OrmIndexField must be used in the fields of the class decorated by OrmClass and OrmTokenClass. Each class fields decorated by the OrmField becomes the field of the resource in an Aptos Object.
POA Account is an account that can generate and transfer the transaction. The account has the POA (Power of attorney) creates AptoORM Objects instead of the NFT Creator.
aptos key generate --assume-yes --output-file .key/poa1
aptos init --network devnet --private-key-file .key/poa1 --profile poa1
npx apto_orm poa register -d .key/villain -l .key/poa1
npx apto_orm poa show -l .key/poa1npx apto_orm create src/my_tokens --key .key/poa1 -c MyToken \
-d '{ "uri": "https://raw.githubusercontent.com/neoul/apto_orm/main/resource.png", "description": "ok", "id": 100, "name": "ABC" }'# [How to build, test and run]
# testing
docker build --target apto_orm-testing -t apto_orm-testing .
# Building
docker build -t apto_orm .
# Running
docker run -d -p 8080-8082:8080-8082 -p 9101:9101 -p 50051:50051 -p 5678:5678 --name apto_orm apto_orm
# Downloading keys and .env
curl http://localhost:8082/download.sh | shOr you can setup AptoORM at once.
./run.sh setuporm_creator module provides a signer object that becomes the creator of AptoORM class objects in order to support the programmatic onchain resource handling. The signer object that has OrmCreator resource returns back its signer if the transaction sender (signer) is the owner of the signer object. It also returns the signer if other accounts authorized by the owner through PowerOfAttorney resource declaration. The owner account can register or revoke the authorized accounts directly or via the proof challenge.
orm_class module is used to store the onchain properties of the user-defined class.
orm_module is used to designate the orm_creator and orm_class of your class module.
The orm_module is recorded to your account that is a placeholder to deploy your class module.
orm_object ... TBD
---
ORM Onchain Resource
---
classDiagram
OrmModule "1" --> "1" OrmCreator: refer
OrmModule "1" --> "1" `OrmClass, OrmTokenClass`: refer
UserData .. `OrmObject, OrmToken`: co-locate in an object
`OrmObject, OrmToken` --> "1" `OrmClass, OrmTokenClass`: refer
`OrmClass, OrmTokenClass` "1" --> "1" OrmCreator: refer
class UserData {
+data: any
}
class OrmCreator {
+publisher: address
+extend_ref: ExtendRef
+load_signer()
+load_signer_by_signer_capability()
}
class `OrmClass, OrmTokenClass` {
+creator: OrmCreator
+config: OrmObjectConfig
}
class OrmModule {
+signer: OrmCreator
+class: OrmClass
}
class `OrmObject, OrmToken` {
+class: OrmClass
}
---
title Onchain accounts in ORM Onchain Architecture
---
flowchart
subgraph OwnerAccount
OwnerAccount::Account
end
subgraph AuthorizedAccount
AuthorizedAccount::Account
AuthorizedAccount::PowerOfAttorney
end
subgraph OrmCreator
OrmCreator::ObjectCore
OrmCreator::OrmCreator
end
subgraph OrmClass
OrmClass::ObjectCore
OrmClass::OrmClass
OrmClass::OrmTokenClass
end
subgraph OrmObject
OrmObject::ObjectCore
OrmObject::OrmObject
OrmObject::OrmToken
OrmObject::UserData
end
OwnerAccount -- give authority (POA) --> AuthorizedAccount
OwnerAccount -- create and load OrmCreator --> OrmCreator
AuthorizedAccount -- load OrmCreator to handle OrmObject --> OrmCreator
OrmCreator -- create/delete/update --> OrmObject
OrmCreator -- own --> OrmClass
OrmObject -- refer --> OrmClass
[설명 추가]