A lightweight TypeScript/JavaScript SDK for the Transaction Authorization Protocol (TAP), providing full DIDComm v2 compatibility with WASM-powered cryptography.
- 🔐 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
npm install @taprsvp/agentimport { 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: 'alice@example.com'
},
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);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
});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'
});did: string- The agent's DID (Decentralized Identifier)
Packs a DIDComm message for secure transmission.
const packed = await agent.pack(message);
// packed.message contains the JWS signed messageUnpacks a received DIDComm message.
const message = await agent.unpack(packedMessage);Generates a UUID for message IDs.
const messageId = await agent.generateUUID();Exports the agent's private key as a hex string.
const privateKey = agent.exportPrivateKey();
// Store securely for later useResolves a DID to its DID Document.
const didDoc = await agent.resolve('did:key:z6Mkk...');Cleans up WASM resources.
agent.dispose();Generates a new private key.
import { generatePrivateKey } from '@taprsvp/agent';
const privateKey = await generatePrivateKey('Ed25519');Generates a UUID v4.
import { generateUUID } from '@taprsvp/agent';
const uuid = await generateUUID();Validates a DID format.
import { isValidDID } from '@taprsvp/agent';
if (isValidDID('did:key:z6Mkk...')) {
// Valid DID
}Validates a private key format.
import { isValidPrivateKey } from '@taprsvp/agent';
if (isValidPrivateKey(privateKeyHex)) {
// Valid private key
}Create TAP-compliant messages using helper functions and types from @taprsvp/types:
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
}
]
});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'
}
});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 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'
});The SDK also supports standard DIDComm messages:
const message = await agent.createMessage('BasicMessage', {
content: 'Hello, World!'
});const ping = await agent.createMessage('TrustPing', {
response_requested: true
});const pingResponse = await agent.createMessage('TrustPingResponse', {}, {
thid: originalPingId // Reference to original ping
});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
});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
});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>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();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 }
});The SDK is fully compatible with:
- ✅ Veramo DIDComm implementation
- ✅ DIDComm v2 specification
- ✅ did:key method
- ✅ JWS message format
- ✅ Standard DIDComm message types
- TypeScript bundle: 3.72KB gzipped
- WASM module: 272KB gzipped
- Message operations: < 10ms typical
- Key generation: < 5ms typical
- 🔐 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
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' });
}// 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);Apache-2.0
Contributions are welcome! Please see our contributing guidelines.
For issues and questions, please use the GitHub issue tracker.