🔥 Quickstart ​
Get up and running with MoveAS in minutes! This guide will walk you through creating your first attestation.
Prerequisites ​
- Node.js 20+ installed
- Yarn or npm package manager
- Sui or Aptos testnet access
- Basic knowledge of TypeScript/JavaScript
Installation ​
Install the MoveAS SDK:
bash
npm install @moveas/sdk
# or
yarn add @moveas/sdkExample: Create Your First Attestation (Sui) ​
1. Set Up Environment ​
Create a new project and install dependencies:
bash
mkdir my-moveas-app
cd my-moveas-app
npm init -y
npm install @moveas/sdk @mysten/sui @mysten/bcs2. Create Schema ​
typescript
import { Sas, Codec, StorageType, getKeypair } from '@moveas/sdk';
import { bcs } from '@mysten/bcs';
const network = 'testnet';
const chain = 'sui';
const keypair = getKeypair(); // Or load from env variable
const sas = new Sas(chain, network, keypair);
// Define schema template
const schemaTemplate = 'name: string, age: u64, email: string';
const schemaCodec = new Codec(schemaTemplate);
const schemaBytes = bcs.string().serialize(schemaTemplate).toBytes();
// Register schema
const res = await sas.registerSchema(
new Uint8Array(schemaBytes),
'User Profile',
'User profile information',
'https://example.com',
true // revokable
);
// Extract schema ID from response
let schemaId = '';
for (const created of res.effects?.created || []) {
if (typeof created.owner === 'object' && 'Shared' in created.owner) {
schemaId = created.reference.objectId;
break;
}
}
console.log('Schema ID:', schemaId);3. Create Attestation ​
typescript
// Prepare attestation data
const item = {
name: "Alice",
age: 30n,
email: "alice@example.com"
};
// Encode data according to schema
const encodedItem = schemaCodec.encodeToBytes(item);
// Create attestation (on-chain storage)
const result = await sas.attest(
schemaId,
'0x0', // ref_attestation
keypair.toSuiAddress(), // recipient
BigInt(Date.now() + 1000 * 60 * 60 * 24), // expiration_time (24 hours)
encodedItem,
'Alice\'s Profile',
'User profile attestation',
'https://example.com',
StorageType.ON_CHAIN // on-chain storage
);
// Extract attestation ID
let attestationId = '';
for (const createdObject of result.effects?.created || []) {
if (typeof createdObject.owner === 'object' && 'AddressOwner' in createdObject.owner) {
attestationId = createdObject.reference.objectId;
break;
}
}
console.log('Attestation ID:', attestationId);4. Retrieve Attestation ​
typescript
import { getAttestation } from '@moveas/sdk';
// Get attestation from chain
const attestation = await getAttestation(attestationId, chain, network);
console.log('Attestation:', attestation);
console.log('Attestor:', attestation.attestor);
console.log('Recipient:', attestation.recipient);
// Decode data
const decodedData = schemaCodec.decodeFromBytes(attestation.data!);
console.log('Decoded data:', decodedData);Example: Create Off-Chain Attestation (Sui) ​
For larger data or cost optimization, use off-chain storage:
typescript
import { WalrusClient, blake2b256, getClient, getAttestationData } from '@moveas/sdk';
// Initialize Walrus client
const client = getClient(chain, network);
const walrusClient = new WalrusClient(client, {
network,
uploadRelay: {
host: 'https://upload-relay.testnet.walrus.space',
sendTip: { max: 1_000 },
},
storageNodeClientOptions: {
timeout: 60_000,
},
});
// Prepare data
const item = {
name: "Bob",
bio: "A long biography...", // Large data
achievements: ["Achievement 1", "Achievement 2"]
};
const encodedItem = schemaCodec.encodeToBytes(item);
// Calculate data hash
const dataHash = blake2b256(encodedItem);
// Upload to Walrus
const uploadResult = await walrusClient.uploadData(encodedItem, keypair, 3, false);
// Create off-chain attestation
const result = await sas.attest(
schemaId,
'0x0',
keypair.toSuiAddress(),
BigInt(Date.now() + 1000 * 60 * 60 * 24),
encodedItem, // Original data (not stored, only for reference)
'Bob\'s Profile',
'User profile with large data',
'https://example.com',
StorageType.OFF_CHAIN,
uploadResult.suiObjectId,
uploadResult.blobId,
dataHash,
false, // not encrypted
undefined, // no seal nonce
undefined // no seal policy
);
// Retrieve data
const retrievedData = await getAttestationData(
attestationId,
keypair.toSuiAddress(),
chain,
network,
walrusClient
);
const decodedData = schemaCodec.decodeFromBytes(retrievedData);
console.log('Decoded data:', decodedData);Example: Create Encrypted Attestation (Sui) ​
For sensitive data, use Seal encryption:
typescript
import { SealWrapper, computeSealKeyId, SEAL_KEY_SERVERS, getPackageId } from '@moveas/sdk';
import { SessionKey } from '@mysten/seal';
// Initialize Seal wrapper
const sealWrapper = new SealWrapper(client, {
serverConfigs: SEAL_KEY_SERVERS.testnet.map((objectId) => ({
objectId,
weight: 1,
})),
verifyKeyServers: false,
timeout: 10_000,
});
const packageId = getPackageId(chain, network);
const attestorAddress = keypair.toSuiAddress();
// Generate nonce for Seal
const sealNonce = crypto.getRandomValues(new Uint8Array(16));
const sealIdHex = computeSealKeyId(attestorAddress, sealNonce);
// Encrypt data
const sealPolicy = {
packageId,
id: sealIdHex,
threshold: 1,
keyServers: SEAL_KEY_SERVERS.testnet.map((objectId) => ({
objectId,
weight: 1,
})),
};
const { encryptedData } = await sealWrapper.encryptData(encodedItem, sealPolicy);
// Calculate hash of original data (before encryption)
const dataHash = blake2b256(encodedItem);
// Upload encrypted data to Walrus
const uploadResult = await walrusClient.uploadData(encryptedData, keypair, 3, false);
// Create encrypted attestation
const result = await sas.attest(
schemaId,
'0x0',
recipientAddress, // Recipient who can decrypt
BigInt(Date.now() + 1000 * 60 * 60 * 24),
encodedItem, // Original data (not stored)
'Sensitive Profile',
'Encrypted user profile',
'https://example.com',
StorageType.OFF_CHAIN,
uploadResult.suiObjectId,
uploadResult.blobId,
dataHash,
true, // encrypted
sealNonce, // Seal nonce
undefined // seal policy ID
);Example: Create Attestation (Aptos) ​
For Aptos chain:
typescript
import { Aas, Codec } from '@moveas/sdk';
import { Account, Network, Ed25519PrivateKey, Hex } from "@aptos-labs/ts-sdk";
import { bcs } from '@mysten/bcs';
// Set up account
const privateKeyBytes = Hex.fromHexString(process.env.PRIVATE_KEY || "").toUint8Array();
const privateKey = new Ed25519PrivateKey(privateKeyBytes);
const account = Account.fromPrivateKey({ privateKey });
const network = Network.TESTNET;
const aas = new Aas(account, 'aptos', network);
// Create schema
const schemaTemplate = "name: string, age: u64";
const codec = new Codec(schemaTemplate);
const schema = bcs.string().serialize(schemaTemplate).toBytes();
const res = await aas.createSchema(
schema,
"User Profile",
"Description",
"https://example.com",
false, // revokable
'0x0' // resolver
);
// Extract schema address
const events = (res as any).events;
let schemaAddress = "";
for (const event of events) {
if (event.type.includes("SchemaCreated")) {
schemaAddress = event.data.schema_address;
break;
}
}
// Create attestation
const item = {
name: "Alice",
age: 30n,
};
const attestationRaw = codec.encodeToBytes(item);
const res2 = await aas.createAttestation(
account.accountAddress.toString(),
schemaAddress,
'0x0',
0, // expiration_time
false, // revokable
attestationRaw
);
console.log('Attestation created:', res2);Next Steps ​
- Learn about Core Concepts
- Explore the Architecture
- Check out the SDK Documentation
- Explore the Contracts Documentation for smart contract details
Next: Core Concepts →