@taprsvp/agent
v0.6.0-PRE-1
Published
TypeScript wrapper for TAP WASM Agent - Browser-optimized message packing/unpacking with flexible key management
Readme
@taprsvp/agent
A lightweight TypeScript/JavaScript SDK for the Transaction Authorization Protocol (TAP), providing full DIDComm v2 compatibility with WASM-powered cryptography.
Features
- 🔐 Full DIDComm v2 Support - Compatible with Veramo and other DIDComm implementations
- 🚀 Lightweight - Only 3.72KB gzipped TypeScript + 272KB WASM
- 🔑 Multiple Key Types - Ed25519, P-256, and secp256k1
- 📦 Zero Dependencies - Only requires
@taprsvp/typesfor TypeScript types - 🌐 Browser & Node.js - Works in both environments
- ⚡ High Performance - WASM-powered cryptography
- 🛡️ TAP Compliant - Supports all TAP message types and specifications
Installation
npm install @taprsvp/agentQuick Start
import { TapAgent } from '@taprsvp/agent';
// Create a new agent with auto-generated keys
const agent = await TapAgent.create({ keyType: 'Ed25519' });
console.log('Agent DID:', agent.did);
// Create a TAP Transfer message using @taprsvp/types
import { createTransferMessage } from '@taprsvp/agent';
import type { Transfer } from '@taprsvp/types';
const transfer: Transfer = createTransferMessage({
from: agent.did,
to: ['did:key:z6Mkk7yqnGF3YwTrLpqrW6PGsKci7dNqh1CjnvMbzrMerSeL'],
amount: '100.00',
asset: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
originator: {
'@id': agent.did,
'@type': 'https://schema.org/Person',
name: 'Alice Smith',
email: '[email protected]'
},
beneficiary: {
'@id': 'did:key:z6Mkk7yqnGF3YwTrLpqrW6PGsKci7dNqh1CjnvMbzrMerSeL',
'@type': 'https://schema.org/Person',
name: 'Bob Jones'
},
agents: [] // Agents involved in the transaction
});
// Pack the message for secure transmission
const packed = await agent.pack(transfer);
console.log('Packed message ready for transmission');
// Unpack received messages
const unpacked = await agent.unpack(receivedMessage);
console.log('Received:', unpacked);API Reference
TapAgent
Static Methods
TapAgent.create(options?: TapAgentOptions): Promise<TapAgent>
Creates a new TAP agent with auto-generated keys.
const agent = await TapAgent.create({
keyType: 'Ed25519', // or 'P256' or 'secp256k1'
resolver: customResolver // optional DID resolver
});TapAgent.fromPrivateKey(privateKey: string, options?: TapAgentOptions): Promise<TapAgent>
Creates a TAP agent from an existing private key.
import { generatePrivateKey } from '@taprsvp/agent';
const privateKey = await generatePrivateKey('Ed25519');
const agent = await TapAgent.fromPrivateKey(privateKey, {
keyType: 'Ed25519'
});Instance Properties
did: string- The agent's DID (Decentralized Identifier)
Instance Methods
pack(message: DIDCommMessage): Promise<PackedMessage>
Packs a DIDComm message for secure transmission.
const packed = await agent.pack(message);
// packed.message contains the JWS signed messageunpack(packedMessage: string): Promise<DIDCommMessage>
Unpacks a received DIDComm message.
const message = await agent.unpack(packedMessage);generateUUID(): Promise<string>
Generates a UUID for message IDs.
const messageId = await agent.generateUUID();exportPrivateKey(): string
Exports the agent's private key as a hex string.
const privateKey = agent.exportPrivateKey();
// Store securely for later useresolve(did: string): Promise<DIDDocument | null>
Resolves a DID to its DID Document.
const didDoc = await agent.resolve('did:key:z6Mkk...');dispose(): void
Cleans up WASM resources.
agent.dispose();Utility Functions
generatePrivateKey(keyType?: KeyType): Promise<string>
Generates a new private key.
import { generatePrivateKey } from '@taprsvp/agent';
const privateKey = await generatePrivateKey('Ed25519');generateUUID(): Promise<string>
Generates a UUID v4.
import { generateUUID } from '@taprsvp/agent';
const uuid = await generateUUID();isValidDID(did: string): boolean
Validates a DID format.
import { isValidDID } from '@taprsvp/agent';
if (isValidDID('did:key:z6Mkk...')) {
// Valid DID
}isValidPrivateKey(key: string): boolean
Validates a private key format.
import { isValidPrivateKey } from '@taprsvp/agent';
if (isValidPrivateKey(privateKeyHex)) {
// Valid private key
}Creating TAP Messages
Create TAP-compliant messages using helper functions and types from @taprsvp/types:
Transfer
import { createTransferMessage } from '@taprsvp/agent';
import type { Transfer } from '@taprsvp/types';
const transfer: Transfer = createTransferMessage({
from: originatorDid,
to: [beneficiaryDid],
amount: '100.00',
asset: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
originator: {
'@id': originatorDid,
'@type': 'https://schema.org/Person',
name: 'Alice Smith'
},
beneficiary: {
'@id': beneficiaryDid,
'@type': 'https://schema.org/Organization',
name: 'Example Corp',
leiCode: '969500KN90DZLPGW6898'
},
memo: 'Payment for services',
agents: [ // Optional agents involved in the transaction
{
'@id': agentDid,
role: 'SettlementAddress',
for: originatorDid
}
]
});Payment
import { createPaymentMessage } from '@taprsvp/agent';
import type { Payment } from '@taprsvp/types';
const payment: Payment = createPaymentMessage({
from: merchantDid,
to: [customerDid],
amount: '50.00',
currency: 'USD',
merchant: {
'@id': merchantDid,
'@type': 'https://schema.org/Organization',
name: 'Example Merchant',
mcc: '5812', // Restaurant
url: 'https://merchant.example.com'
},
invoice: {
invoiceNumber: 'INV-001',
items: [{ description: 'Product', quantity: 1, unitPrice: '50.00' }],
total: '50.00'
}
});Connect
const connect = await agent.createMessage('Connect', {
constraints: {
asset_types: ['eip155:1/erc20:*'],
currency_types: ['USD', 'EUR'],
transaction_limits: {
min_amount: '10.00',
max_amount: '10000.00'
}
}
});Authorize / Reject / Settle
// Authorize a transaction
const authorize = await agent.createMessage('Authorize', {
transaction_id: 'transfer-123',
settlement_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7'
});
// Reject a transaction
const reject = await agent.createMessage('Reject', {
transaction_id: 'transfer-123',
reason: 'Insufficient funds'
});
// Settle a transaction
const settle = await agent.createMessage('Settle', {
transaction_id: 'transfer-123',
settlement_id: 'eip155:1:0x123...abc'
});DIDComm Standard Messages
The SDK also supports standard DIDComm messages:
BasicMessage
const message = await agent.createMessage('BasicMessage', {
content: 'Hello, World!'
});TrustPing
const ping = await agent.createMessage('TrustPing', {
response_requested: true
});TrustPingResponse
const pingResponse = await agent.createMessage('TrustPingResponse', {}, {
thid: originalPingId // Reference to original ping
});Threading
Support for message threading to maintain conversation context:
const initialMessage = await agent.createMessage('Transfer', transferData, {
thid: 'conversation-123', // Thread ID
pthid: 'parent-thread-456' // Parent thread ID
});
// Continue the conversation
const response = await agent.createMessage('Authorize', authData, {
thid: 'conversation-123' // Same thread ID
});Custom DID Resolver
Provide a custom DID resolver for advanced use cases:
const customResolver = async (did: string): Promise<DIDDocument | null> => {
// Your resolution logic here
return didDocument;
};
const agent = await TapAgent.create({
keyType: 'Ed25519',
resolver: customResolver
});Browser Usage
The SDK works seamlessly in browsers:
<script type="module">
import { TapAgent } from '@taprsvp/agent';
const agent = await TapAgent.create();
console.log('Agent DID:', agent.did);
</script>Node.js Usage
Full support for Node.js environments:
import { TapAgent } from '@taprsvp/agent';
async function main() {
const agent = await TapAgent.create();
console.log('Agent DID:', agent.did);
}
main();TypeScript Support
Full TypeScript support with comprehensive type definitions:
import { TapAgent, DIDCommMessage, KeyType } from '@taprsvp/agent';
import type { Transfer, Payment } from '@taprsvp/types';
const agent = await TapAgent.create({ keyType: 'Ed25519' as KeyType });
const transfer: DIDCommMessage<Transfer> = await agent.createMessage('Transfer', {
// TypeScript will provide full type checking here
amount: '100.00',
asset: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
originator: { '@id': agent.did },
beneficiary: { '@id': recipientDid }
});Interoperability
The SDK is fully compatible with:
- ✅ Veramo DIDComm implementation
- ✅ DIDComm v2 specification
- ✅ did:key method
- ✅ JWS message format
- ✅ Standard DIDComm message types
Performance
- TypeScript bundle: 3.72KB gzipped
- WASM module: 272KB gzipped
- Message operations: < 10ms typical
- Key generation: < 5ms typical
Security
- 🔐 Private keys never leave the WASM module
- 🔑 Secure key generation using cryptographically secure random
- ✅ Standard cryptographic algorithms (Ed25519, P-256, secp256k1)
- 📦 Minimal attack surface with zero runtime dependencies
Examples
Key Management
import { TapAgent, generatePrivateKey } from '@taprsvp/agent';
// Generate and store a private key
const privateKey = await generatePrivateKey('Ed25519');
localStorage.setItem('tapAgent.privateKey', privateKey);
// Later, restore the agent
const storedKey = localStorage.getItem('tapAgent.privateKey');
if (storedKey) {
const agent = await TapAgent.fromPrivateKey(storedKey, { keyType: 'Ed25519' });
}Message Exchange
// Alice creates and sends a transfer
const alice = await TapAgent.create();
const transfer = await alice.createMessage('Transfer', {
amount: '100.00',
asset: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
originator: {
'@id': alice.did,
'@type': 'https://schema.org/Person',
name: 'Alice Smith'
},
beneficiary: {
'@id': bobDid,
'@type': 'https://schema.org/Person',
name: 'Bob Jones'
},
agents: [] // Add any agents here if needed
});
transfer.to = [bobDid];
const packed = await alice.pack(transfer);
// Send packed.message to Bob...
// Bob receives and processes the transfer
const bob = await TapAgent.create();
const received = await bob.unpack(packed.message);
console.log('Received transfer for:', received.body.amount);
// Bob authorizes the transfer
const authorize = await bob.createMessage('Authorize', {
transaction_id: received.id,
settlement_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7'
}, {
thid: received.id,
to: [alice.did]
});
const authPacked = await bob.pack(authorize);License
Apache-2.0
Contributing
Contributions are welcome! Please see our contributing guidelines.
Support
For issues and questions, please use the GitHub issue tracker.
