Official TypeScript/JavaScript SDK for Amadeus Protocol - Core utilities for serialization, cryptography, transaction building, and API client.
npm install @amadeus-protocol/sdk
# or
yarn add @amadeus-protocol/sdk
# or
pnpm add @amadeus-protocol/sdk
# or
bun add @amadeus-protocol/sdkESM-only: this package is published as pure ESM (
"type": "module"). Use Node.js 20+ with"type": "module"in yourpackage.json, or any modern bundler (Vite, webpack, esbuild, Metro). For CommonJS consumers, run viatsx. See Troubleshooting for the1.0.xERR_MODULE_NOT_FOUNDissue and upgrade path.
contract.view()— read-only contract executionchain.getByFilter()/chain.getKpi()— filtered tx queries + protocol KPIsproof.getContractStateProof()— merkle proofs for contract statesubmitAndWait(txPacked, { finalized: true })— wait for finality instead of confirmation- NFT contract —
NFT_ABI,buildNftTransfer/Mint/CreateCollection,TransactionBuilder.nftTransfer/nftMint/nftCreateCollection - ESM fix — published
dist/*.jsnow resolves correctly under rawnode(the1.0.xERR_MODULE_NOT_FOUNDbug)
See the CHANGELOG for full release history.
- Canonical Serialization (VecPack): Deterministic encoding/decoding for cryptographic operations
- Cryptographic Operations: BLS12-381 key generation, signing, and verification
- Password-Based Encryption: Secure AES-GCM encryption with PBKDF2 key derivation for wallet data
- Transaction Building: Create and sign Amadeus protocol transactions
- Token Conversions: Convert between atomic units and human-readable amounts
- Encoding Utilities: Base58 and Base64 encoding/decoding for addresses, keys, and binary data
- API Client: Full-featured HTTP client for interacting with Amadeus nodes
- Type Safety: Complete TypeScript definitions for all APIs
- Zero Dependencies: Uses native fetch (no axios or other HTTP libraries)
import { AmadeusSDK } from '@amadeus-protocol/sdk'
// Initialize SDK (uses default node URL if not specified)
const sdk = new AmadeusSDK({
baseUrl: 'https://mainnet-rpc.ama.one/api'
})
// Query chain
const tip = await sdk.chain.getTip()
console.log('Current height:', tip.entry.header.height)
// Query wallet balance
const balance = await sdk.wallet.getBalance('5Kd3N...', 'AMA')
console.log('Balance:', balance.balance.float)
// Submit transaction
const result = await sdk.transaction.submit(txPacked)import { AmadeusSDK } from '@amadeus-protocol/sdk'
const sdk = new AmadeusSDK({
baseUrl: 'https://mainnet-rpc.ama.one/api',
timeout: 30000 // Optional: custom timeout
})
// Chain API
const stats = await sdk.chain.getStats()
const tip = await sdk.chain.getTip()
const entry = await sdk.chain.getByHash('5Kd3N...')
const { txs, cursor } = await sdk.chain.getByFilter({ contract: 'Coin', function: 'transfer' })
const { kpi } = await sdk.chain.getKpi()
// Wallet API
const balance = await sdk.wallet.getBalance('5Kd3N...', 'AMA')
const allBalances = await sdk.wallet.getAllBalances('5Kd3N...')
// Transaction API
const result = await sdk.transaction.submit(txPacked)
const confirmed = await sdk.transaction.submitAndWait(txPacked)
const finalized = await sdk.transaction.submitAndWait(txPacked, { finalized: true })
const tx = await sdk.transaction.get('5Kd3N...')
// Contract API
const contractData = await sdk.contract.get(key)
const richlist = await sdk.contract.getRichlist()
const { success, result } = await sdk.contract.view({
contract: 'LockupPrime',
function: 'view_balance',
args: ['my_vault']
})
// Epoch API
const scores = await sdk.epoch.getScore()
const emission = await sdk.epoch.getEmissionAddress('5Kd3N...')
// Peer API
const nodes = await sdk.peer.getNodes()
const trainers = await sdk.peer.getTrainers()
// Proof API
const validatorProof = await sdk.proof.getValidators(entryHash)
const stateProof = await sdk.proof.getContractStateProof(stateKey)import { generateKeypair, derivePublicKeyFromSeedBase58 } from '@amadeus-protocol/sdk'
// Generate a new keypair
const keypair = generateKeypair()
console.log(keypair.publicKey) // Base58 public key
console.log(keypair.privateKey) // Base58 private key (seed)
// Derive public key from existing seed
const publicKey = derivePublicKeyFromSeedBase58(keypair.privateKey)import { TransactionBuilder, fromBase58, toAtomicAma } from '@amadeus-protocol/sdk'
// Instance-based usage (convenient for multiple transactions)
const builder = new TransactionBuilder('5Kd3N...') // Base58 encoded seed
// Option 1: Build and sign in one step (convenience)
const { txHash, txPacked } = builder.transfer({
recipient: '5Kd3N...', // Base58 encoded recipient address
amount: 10.5, // Amount in human-readable format
symbol: 'AMA' // Token symbol
})
// Option 2: Build unsigned, then sign (more control)
const unsignedTx = builder.buildTransfer({
recipient: '5Kd3N...',
amount: 10.5,
symbol: 'AMA'
})
// Can inspect or modify unsignedTx before signing
const { txHash, txPacked } = builder.sign(unsignedTx)
// Option 3: Build custom transaction and sign
const unsignedTx = builder.build('Coin', 'transfer', [
fromBase58('5Kd3N...'), // Recipient bytes
toAtomicAma(10.5).toString(), // Amount in atomic units
'AMA'
])
const { txHash, txPacked } = builder.sign(unsignedTx)
// Option 4: Build and sign custom transaction (convenience)
const { txHash, txPacked } = builder.buildAndSign('Coin', 'transfer', [
fromBase58('5Kd3N...'),
toAtomicAma(10.5).toString(),
'AMA'
])The recommended pattern for built-in contracts. Pass any ABI to builder.contract(abi) and get fully-typed function calls:
import {
TransactionBuilder,
LOCKUP_PRIME_ABI,
LOCKUP_ABI,
toAtomicAma
} from '@amadeus-protocol/sdk'
const builder = new TransactionBuilder('5Kd3N...')
// LockupPrime — auto-typed methods derived from the ABI
builder.contract(LOCKUP_PRIME_ABI).lock({ amount: toAtomicAma(100).toString(), tier: '30d' })
builder.contract(LOCKUP_PRIME_ABI).unlock({ vaultIndex: '3' })
builder.contract(LOCKUP_PRIME_ABI).daily_checkin({ vaultIndex: '7' })
// Lockup
builder.contract(LOCKUP_ABI).unlock({ vaultIndex: '5' })The Nft built-in contract has dedicated builder methods. NFT amounts are integer counts, not AMA atomic units.
const builder = new TransactionBuilder(privateKey)
// Create a collection (caller becomes owner)
builder.nftCreateCollection({ collection: 'AGENTIC', soulbound: false })
// Mint tokens (collection owner only)
builder.nftMint({ recipient: '5Kd3N...', amount: 10, collection: 'AGENTIC', token: '1' })
// Transfer
builder.nftTransfer({ recipient: '5Kd3N...', amount: 1, collection: 'AGENTIC', token: '1' })Static variants: TransactionBuilder.buildSignedNftTransfer/Mint/CreateCollection(input) — each takes the same params plus senderPrivkey.
The SDK supports two patterns. Pick whichever fits your workflow.
The TransactionBuilder instance methods build and sign in one call. Best for app code where you have the private key in hand.
import { TransactionBuilder, LOCKUP_PRIME_ABI, toAtomicAma } from '@amadeus-protocol/sdk'
const builder = new TransactionBuilder('5Kd3N...') // Base58 seed
// Coin transfer
const a = builder.transfer({ recipient: '5Kd3N...', amount: 10.5, symbol: 'AMA' })
// ABI-driven (any contract)
const b = builder.contract(LOCKUP_PRIME_ABI).lock({
amount: toAtomicAma(100).toString(),
tier: '30d'
})
// NFT
const c = builder.nftTransfer({
recipient: '5Kd3N...',
amount: 1,
collection: 'AGENTIC',
token: '1'
})
// All return { txHash, txPacked } ready for sdk.transaction.submit(txPacked)Build a ContractCall with a standalone helper or createContract(ABI), then sign it independently with TransactionBuilder.signCall(privkey, call). Useful when:
- You want to inspect or log the call before signing
- The signing key lives somewhere else (HSM, separate process, separate machine)
- You want to batch-build and sign at the end
import {
TransactionBuilder,
createContract,
LOCKUP_PRIME_ABI,
buildCoinTransfer,
buildNftTransfer,
toAtomicAma
} from '@amadeus-protocol/sdk'
// Build a ContractCall — three ways:
// A. Standalone helper (Coin)
const callA = buildCoinTransfer({ recipient: '5Kd3N...', amount: 10.5, symbol: 'AMA' })
// B. Standalone helper (NFT)
const callB = buildNftTransfer({
recipient: '5Kd3N...',
amount: 1,
collection: 'AGENTIC',
token: '1'
})
// C. ABI-driven, any contract
const lockupPrime = createContract(LOCKUP_PRIME_ABI)
const callC = lockupPrime.lock({ amount: toAtomicAma(100).toString(), tier: '30d' })
// Inspect if you want
console.log('Will call:', callC.contract, callC.method, callC.args)
// Sign with any private key (no builder instance needed)
const { txHash, txPacked } = TransactionBuilder.signCall('5Kd3N...', callC)If you need to inspect the full unsigned transaction (nonce, signer, action) before signing:
const builder = new TransactionBuilder('5Kd3N...')
const unsigned = builder.buildTransfer({ recipient: '5Kd3N...', amount: 10.5, symbol: 'AMA' })
console.log('Nonce:', unsigned.tx.nonce)
console.log('Action:', unsigned.tx.action)
const { txHash, txPacked } = builder.sign(unsigned)import {
TransactionBuilder,
fromBase58,
toAtomicAma,
getPublicKey,
deriveSkAndSeed64FromBase58Seed
} from '@amadeus-protocol/sdk'
// Option 1: Build and sign transfer in one step (convenience)
const { txHash, txPacked } = TransactionBuilder.buildSignedTransfer({
senderPrivkey: '5Kd3N...', // Base58 encoded seed
recipient: '5Kd3N...', // Base58 encoded recipient address
amount: 10.5, // Amount in human-readable format
symbol: 'AMA' // Token symbol
})
// Option 2: Build unsigned transfer, then sign
const { seed64 } = deriveSkAndSeed64FromBase58Seed('5Kd3N...')
const signerPubKey = getPublicKey(seed64)
const unsignedTx = TransactionBuilder.buildTransfer(
{ recipient: '5Kd3N...', amount: 10.5, symbol: 'AMA' },
signerPubKey
)
const { txHash, txPacked } = TransactionBuilder.sign(unsignedTx, '5Kd3N...')
// Option 3: Build custom unsigned transaction, then sign
const unsignedTx = TransactionBuilder.build(
signerPubKey,
'Coin', // Contract name
'transfer', // Method name
[fromBase58('5Kd3N...'), toAtomicAma(10.5).toString(), 'AMA']
)
const { txHash, txPacked } = TransactionBuilder.sign(unsignedTx, '5Kd3N...')
// Option 4: Build and sign custom transaction (convenience)
const { seed64, sk } = deriveSkAndSeed64FromBase58Seed('5Kd3N...')
const signerPubKey = getPublicKey(seed64)
const { txHash, txPacked } = TransactionBuilder.buildAndSign(signerPubKey, sk, 'Coin', 'transfer', [
fromBase58('5Kd3N...'),
toAtomicAma(10.5).toString(),
'AMA'
])import { encode, decode } from '@amadeus-protocol/sdk'
// Encode data to canonical format
const data = {
foo: 'bar',
count: 42,
items: [1, 2, 3]
}
const encoded = encode(data)
// Decode data from canonical format
const decoded = decode(encoded)import { toAtomicAma, fromAtomicAma } from '@amadeus-protocol/sdk'
// Convert to atomic units
const atomic = toAtomicAma(1.5) // Returns 1500000000
// Convert from atomic units
const ama = fromAtomicAma(1500000000) // Returns 1.5import { generateMnemonic, validateMnemonic, mnemonicToSeedBase58 } from '@amadeus-protocol/sdk'
// Generate a 12-word mnemonic
const mnemonic = generateMnemonic()
// Validate a mnemonic
if (validateMnemonic(mnemonic)) {
// Derive a Base58 seed (compatible with TransactionBuilder)
const seedBase58 = mnemonicToSeedBase58(mnemonic)
}import { toBase58, fromBase58, uint8ArrayToBase64, base64ToUint8Array } from '@amadeus-protocol/sdk'
// Base58 encoding
const encoded = toBase58(new Uint8Array([1, 2, 3]))
const decoded = fromBase58('5Kd3N...')
// Base64 encoding
const base64 = uint8ArrayToBase64(new Uint8Array([1, 2, 3]))
const bytes = base64ToUint8Array(base64)import { encryptWithPassword, decryptWithPassword } from '@amadeus-protocol/sdk'
// Encrypt sensitive data (e.g., private keys)
const encrypted = await encryptWithPassword('sensitive wallet data', 'my-password')
// Returns: { encryptedData, iv, salt } (all Base64 encoded)
// Decrypt the data
const decrypted = await decryptWithPassword(encrypted, 'my-password')
// Returns: 'sensitive wallet data'AMADEUS_PUBLIC_KEY_BYTE_LENGTH: Byte length of public key (48)AMADEUS_SEED_BYTE_LENGTH: Byte length of seed (64)AMA_TOKEN_DECIMALS: Number of decimal places (9)AMA_TOKEN_DECIMALS_MULTIPLIER: Multiplier for conversions (10^9)AMA_TRANSFER_FEE: Network transfer fee (0.02)EXPLORER_URL: Default explorer URLNODE_API_URL: Default node API URL
encode(term: SerializableValue): Uint8Array- Encode value to canonical formatdecode(bytes: Uint8Array | number[]): DecodedValue- Decode from canonical format
generateKeypair(): KeyPair- Generate a new keypairgeneratePrivateKey(): Uint8Array- Generate a random 64-byte seedgetPublicKey(seed64: Uint8Array): Uint8Array- Derive public key from seedderivePublicKeyFromSeedBase58(base58Seed: string): string- Derive public key from Base58 seedderiveSkAndSeed64FromBase58Seed(base58Seed64: string)- Derive secret key and seed
generateMnemonic(): string- Generate a 12-word BIP39 mnemonicvalidateMnemonic(mnemonic: string): boolean- Validate a BIP39 mnemonicmnemonicToSeedBase58(mnemonic: string): string- Derive a Base58 seed from a mnemonicencodeVaultSecret,decodeVaultSecret,detectInputType- Vault helpers
toBase58(buf: Uint8Array): string- Encode bytes to Base58fromBase58(str: string): Uint8Array- Decode Base58 to bytesuint8ArrayToBase64(bytes: Uint8Array): string- Convert bytes to Base64base64ToUint8Array(base64: string): Uint8Array- Convert Base64 to bytesarrayBufferToBase64(buffer: ArrayBuffer): string- Convert ArrayBuffer to Base64base64ToArrayBuffer(base64: string): ArrayBuffer- Convert Base64 to ArrayBufferuint8ArrayToArrayBuffer(bytes: Uint8Array): ArrayBuffer- Convert Uint8Array to ArrayBufferarrayBufferToUint8Array(buffer: ArrayBuffer): Uint8Array- Convert ArrayBuffer to Uint8Array
toAtomicAma(ama: number): number- Convert AMA to atomic unitsfromAtomicAma(atomicAma: number | string): number- Convert atomic units to AMA
encryptWithPassword(plaintext: string, password: string): Promise<EncryptedPayload>- Encrypt data with password (AES-GCM + PBKDF2)decryptWithPassword(payload: EncryptedPayload, password: string): Promise<string>- Decrypt data with passwordgenerateSalt(): Uint8Array- Generate random salt (16 bytes)generateIV(): Uint8Array- Generate random IV (12 bytes)deriveKey(password: string, salt: Uint8Array | ArrayBuffer): Promise<CryptoKey>- Derive AES-GCM key from password
TransactionBuilder- Class for building and signing transactions- Constructor:
new TransactionBuilder(privateKey?: string)- Create a new builder instance - ABI-driven (recommended):
contract(abi)- Returns a typed, signer-bound contract interface; each ABI function becomes a method that builds and signs in one step
- Generic instance methods:
build(contract, method, args, signerPk?): UnsignedTransactionWithHashsign(unsignedTx, signerSk?): BuildTransactionResultbuildAndSign(contract, method, args, signerPk?, signerSk?): BuildTransactionResultbuildFromCall(call): UnsignedTransactionWithHashbuildAndSignCall(call): BuildTransactionResult
- Coin transfer:
buildTransfer(input, signerPk?): UnsignedTransactionWithHashtransfer(input): BuildTransactionResult
- NFT (Nft contract):
nftTransfer({ recipient, amount, collection, token }): BuildTransactionResultnftMint({ recipient, amount, collection, token }): BuildTransactionResultnftCreateCollection({ collection, soulbound? }): BuildTransactionResult
- Lockup / LockupPrime convenience methods:
lockupUnlock({ vaultIndex }): BuildTransactionResultlockupPrimeLock({ amount, tier }): BuildTransactionResultlockupPrimeUnlock({ vaultIndex }): BuildTransactionResultlockupPrimeDailyCheckin({ vaultIndex }): BuildTransactionResult
- Static methods:
signCall,buildFromCall,buildAndSignCall,buildSignedTransfer,buildSignedNft{Transfer,Mint,CreateCollection},buildSignedLockup{Unlock},buildSignedLockupPrime{Lock,Unlock,DailyCheckin}
- Constructor:
as const ABI definitions for built-in contracts. Pass any ABI to createContract(abi) or builder.contract(abi) for fully-typed function calls.
LOCKUP_ABI-Lockup(vesting) —unlock(vaultIndex)LOCKUP_PRIME_ABI-LockupPrime—lock(amount, tier),unlock(vaultIndex),daily_checkin(vaultIndex)NFT_ABI-Nft—transfer,mint,create_collection
Standalone builders that return a ContractCall:
buildCoinTransfer({ recipient, amount, symbol })buildNftTransfer({ recipient, amount, collection, token })buildNftMint({ recipient, amount, collection, token })buildNftCreateCollection({ collection, soulbound? })createContract(abi).fn(params)- generic ABI-driven builderbuildContractCall(abi, fn, params)- lower-level ABI-driven builder
For complete documentation including request/response types, error handling, and end-to-end examples, see docs.ama.one/sdk.
See the examples/ directory for comprehensive usage examples:
- Basic Usage - SDK initialization, key generation, queries
- Transaction Flow - Complete transaction building and submission flow
- API Usage - All API endpoints demonstrated
# Run examples
npm run example:basic
npm run example:tx
npm run example:apiThe SDK includes comprehensive test coverage:
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverageThis package is written in TypeScript and includes full type definitions. All exports are typed and documented.
All errors are thrown as AmadeusSDKError instances with descriptive messages:
import { AmadeusSDK, AmadeusSDKError } from '@amadeus-protocol/sdk'
try {
const balance = await sdk.wallet.getBalance('invalid')
} catch (error) {
if (error instanceof AmadeusSDKError) {
console.error('SDK Error:', error.message)
console.error('Status:', error.status)
console.error('Response:', error.response)
}
}MIT
Contributions are welcome! Please ensure all code follows the existing style and includes appropriate tests.