docs: add comprehensive exchange integration guide
- Document network overview and confirmation requirements - Provide node setup instructions with Docker - Explain address generation for hot/cold wallets - Detail deposit monitoring via WebSocket and polling - Document withdrawal transaction building - Explain hybrid signature format (Ed25519 + Dilithium3) - Include complete API reference - Add security recommendations for exchange operations - Document testnet environment for testing
This commit is contained in:
parent
4a2825f516
commit
960c25eb8a
1 changed files with 532 additions and 0 deletions
532
docs/EXCHANGE_INTEGRATION.md
Normal file
532
docs/EXCHANGE_INTEGRATION.md
Normal file
|
|
@ -0,0 +1,532 @@
|
|||
# Synor Exchange Integration Guide
|
||||
|
||||
This document provides technical specifications for cryptocurrency exchanges to integrate Synor (SYNOR) deposits, withdrawals, and trading.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Network Overview](#network-overview)
|
||||
2. [Node Setup](#node-setup)
|
||||
3. [Address Generation](#address-generation)
|
||||
4. [Deposits](#deposits)
|
||||
5. [Withdrawals](#withdrawals)
|
||||
6. [Transaction Format](#transaction-format)
|
||||
7. [API Reference](#api-reference)
|
||||
8. [Security Considerations](#security-considerations)
|
||||
9. [Test Environment](#test-environment)
|
||||
|
||||
---
|
||||
|
||||
## Network Overview
|
||||
|
||||
### Basic Information
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | Synor |
|
||||
| **Symbol** | SYNOR |
|
||||
| **Decimals** | 8 |
|
||||
| **Smallest Unit** | soma (1 SYNOR = 10^8 somas) |
|
||||
| **Block Time** | ~10 seconds (DAG-based) |
|
||||
| **Consensus** | DAG-based PoW with SPECTRE ordering |
|
||||
| **Signature Scheme** | Hybrid Ed25519 + Dilithium3 (post-quantum) |
|
||||
|
||||
### Network Types
|
||||
|
||||
| Network | Address Prefix | Use Case |
|
||||
|---------|---------------|----------|
|
||||
| Mainnet | `synor1` | Production |
|
||||
| Testnet | `tsynor1` | Testing |
|
||||
|
||||
### Confirmation Requirements
|
||||
|
||||
| Amount | Recommended Confirmations |
|
||||
|--------|---------------------------|
|
||||
| < 100 SYNOR | 10 confirmations |
|
||||
| 100-10,000 SYNOR | 50 confirmations |
|
||||
| > 10,000 SYNOR | 100 confirmations |
|
||||
|
||||
---
|
||||
|
||||
## Node Setup
|
||||
|
||||
### Hardware Requirements
|
||||
|
||||
**Minimum:**
|
||||
- CPU: 4 cores
|
||||
- RAM: 8 GB
|
||||
- Storage: 100 GB SSD
|
||||
- Network: 100 Mbps
|
||||
|
||||
**Recommended (Exchange):**
|
||||
- CPU: 8+ cores
|
||||
- RAM: 32 GB
|
||||
- Storage: 500 GB NVMe SSD
|
||||
- Network: 1 Gbps
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
synor-node:
|
||||
image: synor/synord:latest
|
||||
container_name: synor-exchange-node
|
||||
restart: always
|
||||
command:
|
||||
- "run"
|
||||
- "--p2p-port=16511"
|
||||
- "--rpc-host=0.0.0.0"
|
||||
- "--rpc-port=16110"
|
||||
- "--ws-port=16111"
|
||||
- "--seeds=seed1.synor.cc:16511,seed2.synor.cc:16511"
|
||||
ports:
|
||||
- "16511:16511" # P2P (public)
|
||||
- "127.0.0.1:16110:16110" # RPC (internal only)
|
||||
- "127.0.0.1:16111:16111" # WebSocket (internal only)
|
||||
volumes:
|
||||
- synor-data:/data/synor
|
||||
environment:
|
||||
- RUST_LOG=info
|
||||
- SYNOR_NETWORK=mainnet
|
||||
|
||||
volumes:
|
||||
synor-data:
|
||||
```
|
||||
|
||||
### Node Health Check
|
||||
|
||||
```bash
|
||||
# Check sync status
|
||||
curl -X POST http://localhost:16110 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"synor_getSyncStatus","params":[],"id":1}'
|
||||
|
||||
# Response when synced:
|
||||
# {"result":{"synced":true,"currentBlock":1234567,"highestBlock":1234567}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Address Generation
|
||||
|
||||
### Address Format
|
||||
|
||||
Synor addresses use Bech32m encoding:
|
||||
|
||||
```
|
||||
synor1qz232pysw8kezv2f4qxnhdufrlx5cmq78522mpuf8x5qlxu6j8sgcp05get
|
||||
└────┘└──────────────────────────────────────────────────────────┘
|
||||
HRP Base32-encoded payload
|
||||
```
|
||||
|
||||
- **HRP (Human Readable Part):** `synor1` (mainnet) or `tsynor1` (testnet)
|
||||
- **Payload:** 32-byte Blake3 hash of the hybrid public key
|
||||
- **Checksum:** Bech32m checksum (6 characters)
|
||||
|
||||
### Generating Addresses
|
||||
|
||||
#### Using the CLI
|
||||
|
||||
```bash
|
||||
# Generate new address
|
||||
synor-cli wallet new
|
||||
|
||||
# Derive address from mnemonic
|
||||
synor-cli wallet recover --mnemonic "your 24 word phrase..."
|
||||
```
|
||||
|
||||
#### Using the SDK (Rust)
|
||||
|
||||
```rust
|
||||
use synor_crypto::{generate_keypair, public_key_to_address, Network};
|
||||
|
||||
// Generate new keypair
|
||||
let keypair = generate_keypair();
|
||||
|
||||
// Get address
|
||||
let address = public_key_to_address(&keypair.public_key, Network::Mainnet);
|
||||
// Returns: "synor1qz232pysw8kezv2f4qxnhdufrlx5cmq78522mpuf8x5qlxu6j8sgcp05get"
|
||||
```
|
||||
|
||||
#### Using the SDK (JavaScript)
|
||||
|
||||
```javascript
|
||||
import { createWallet, publicKeyToAddress } from '@synor/sdk';
|
||||
|
||||
// Generate wallet from mnemonic
|
||||
const mnemonic = generateMnemonic(24);
|
||||
const wallet = await createWallet(mnemonic, '', 'mainnet');
|
||||
|
||||
console.log(wallet.address);
|
||||
// "synor1qz232pysw8kezv2f4qxnhdufrlx5cmq78522mpuf8x5qlxu6j8sgcp05get"
|
||||
```
|
||||
|
||||
### Address Validation
|
||||
|
||||
```javascript
|
||||
// Validate address format
|
||||
function isValidSynorAddress(address) {
|
||||
const mainnetRegex = /^synor1[a-z0-9]{58}$/;
|
||||
const testnetRegex = /^tsynor1[a-z0-9]{59}$/;
|
||||
return mainnetRegex.test(address) || testnetRegex.test(address);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deposits
|
||||
|
||||
### Recommended Flow
|
||||
|
||||
1. **Generate unique deposit address per user**
|
||||
2. **Monitor address via WebSocket or polling**
|
||||
3. **Wait for required confirmations**
|
||||
4. **Credit user account**
|
||||
|
||||
### Monitoring Deposits
|
||||
|
||||
#### WebSocket Subscription
|
||||
|
||||
```javascript
|
||||
const ws = new WebSocket('ws://localhost:16111');
|
||||
|
||||
ws.onopen = () => {
|
||||
// Subscribe to address transactions
|
||||
ws.send(JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'synor_subscribeAddress',
|
||||
params: ['synor1qz232...'],
|
||||
id: 1
|
||||
}));
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data);
|
||||
if (msg.method === 'synor_addressNotification') {
|
||||
const { txId, amount, confirmations } = msg.params;
|
||||
console.log(`Deposit: ${amount} SYNOR (${confirmations} confirms)`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### Polling Method
|
||||
|
||||
```javascript
|
||||
async function checkDeposits(address, lastCheckedBlock) {
|
||||
const response = await rpc('synor_getAddressTransactions', [
|
||||
address,
|
||||
{ fromBlock: lastCheckedBlock, limit: 100 }
|
||||
]);
|
||||
|
||||
for (const tx of response.transactions) {
|
||||
if (tx.type === 'receive' && tx.confirmations >= REQUIRED_CONFIRMS) {
|
||||
await creditUser(address, tx.amount, tx.txId);
|
||||
}
|
||||
}
|
||||
|
||||
return response.currentBlock;
|
||||
}
|
||||
```
|
||||
|
||||
### Deposit Transaction Example
|
||||
|
||||
```json
|
||||
{
|
||||
"txId": "a1b2c3d4e5f6...",
|
||||
"type": "receive",
|
||||
"amount": "100.00000000",
|
||||
"from": "synor1sender...",
|
||||
"to": "synor1exchange...",
|
||||
"confirmations": 50,
|
||||
"blockHash": "block1234...",
|
||||
"timestamp": 1704067200
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Withdrawals
|
||||
|
||||
### Recommended Flow
|
||||
|
||||
1. **Validate withdrawal address**
|
||||
2. **Check exchange hot wallet balance**
|
||||
3. **Build and sign transaction**
|
||||
4. **Broadcast transaction**
|
||||
5. **Monitor confirmation status**
|
||||
6. **Update user withdrawal status**
|
||||
|
||||
### Building a Withdrawal Transaction
|
||||
|
||||
```javascript
|
||||
import { createSendTransactionHybrid, serializeTransaction } from '@synor/sdk';
|
||||
|
||||
async function processWithdrawal(toAddress, amount, wallet) {
|
||||
// Build signed transaction
|
||||
const tx = await createSendTransactionHybrid(
|
||||
wallet.address, // From: exchange hot wallet
|
||||
toAddress, // To: user's address
|
||||
amount, // Amount in SYNOR (e.g., "100.5")
|
||||
wallet // Contains seed, keypair, dilithiumPublicKey
|
||||
);
|
||||
|
||||
// Broadcast
|
||||
const result = await rpc('synor_sendRawTransaction', [
|
||||
serializeTransaction(tx)
|
||||
]);
|
||||
|
||||
return result.txId;
|
||||
}
|
||||
```
|
||||
|
||||
### UTXO Consolidation
|
||||
|
||||
For high-volume exchanges, periodically consolidate small UTXOs:
|
||||
|
||||
```javascript
|
||||
async function consolidateUtxos(wallet) {
|
||||
const utxos = await rpc('synor_getUtxos', [wallet.address]);
|
||||
|
||||
// Only consolidate if many small UTXOs
|
||||
if (utxos.length < 100) return;
|
||||
|
||||
// Filter small UTXOs (< 1 SYNOR)
|
||||
const smallUtxos = utxos.filter(u => parseFloat(u.amount) < 1);
|
||||
|
||||
if (smallUtxos.length < 50) return;
|
||||
|
||||
// Build consolidation transaction (send to self)
|
||||
// ... transaction building code
|
||||
}
|
||||
```
|
||||
|
||||
### Fee Estimation
|
||||
|
||||
```javascript
|
||||
async function estimateFee(fromAddress, toAddress, amount) {
|
||||
const result = await rpc('synor_estimateFee', [{
|
||||
from: fromAddress,
|
||||
to: toAddress,
|
||||
amount: amount
|
||||
}]);
|
||||
|
||||
return {
|
||||
fee: result.fee, // e.g., "0.00001000"
|
||||
feePerByte: result.feePerByte,
|
||||
estimatedSize: result.size // Larger for hybrid signatures
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Transaction Format
|
||||
|
||||
### Hybrid Signatures
|
||||
|
||||
Synor uses **hybrid signatures** combining:
|
||||
|
||||
1. **Ed25519** (64 bytes) - Classical elliptic curve
|
||||
2. **Dilithium3/ML-DSA-65** (~3.3 KB) - Post-quantum lattice-based
|
||||
|
||||
Both signatures must verify for a transaction to be valid.
|
||||
|
||||
### Transaction Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"inputs": [
|
||||
{
|
||||
"previousTxId": "abc123...",
|
||||
"outputIndex": 0,
|
||||
"signature": "ed25519_sig_hex",
|
||||
"hybridSignature": {
|
||||
"ed25519": "64_bytes_hex",
|
||||
"dilithium": "3293_bytes_hex"
|
||||
},
|
||||
"publicKey": "ed25519_pubkey_32_bytes",
|
||||
"dilithiumPublicKey": "dilithium_pubkey_1952_bytes"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "synor1recipient...",
|
||||
"amount": "10000000000" // 100 SYNOR in somas
|
||||
}
|
||||
],
|
||||
"lockTime": 0,
|
||||
"isHybrid": true
|
||||
}
|
||||
```
|
||||
|
||||
### Transaction Size
|
||||
|
||||
Due to Dilithium signatures, Synor transactions are larger than Bitcoin:
|
||||
|
||||
| Component | Size (bytes) |
|
||||
|-----------|-------------|
|
||||
| Base transaction | ~50 |
|
||||
| Per input (hybrid) | ~5,500 |
|
||||
| Per output | ~40 |
|
||||
|
||||
**Example:** 2 inputs, 2 outputs ≈ 11,180 bytes
|
||||
|
||||
---
|
||||
|
||||
## API Reference
|
||||
|
||||
### JSON-RPC Endpoint
|
||||
|
||||
- **HTTP:** `http://localhost:16110`
|
||||
- **WebSocket:** `ws://localhost:16111`
|
||||
|
||||
### Common Methods
|
||||
|
||||
#### synor_getBlockCount
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_getBlockCount","params":[],"id":1}
|
||||
// Response: {"result": 1234567}
|
||||
```
|
||||
|
||||
#### synor_getBalance
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_getBalance","params":["synor1..."],"id":1}
|
||||
// Response: {"result": {"confirmed": "1000.50000000", "pending": "10.00000000"}}
|
||||
```
|
||||
|
||||
#### synor_getUtxos
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_getUtxos","params":["synor1..."],"id":1}
|
||||
// Response: {"result": [{"txId": "...", "outputIndex": 0, "amount": "100.00000000"}]}
|
||||
```
|
||||
|
||||
#### synor_sendRawTransaction
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_sendRawTransaction","params":["serialized_tx"],"id":1}
|
||||
// Response: {"result": {"txId": "abc123..."}}
|
||||
```
|
||||
|
||||
#### synor_getTransaction
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_getTransaction","params":["txId"],"id":1}
|
||||
// Response: {"result": {"txId": "...", "confirmations": 50, ...}}
|
||||
```
|
||||
|
||||
#### synor_getAddressTransactions
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"synor_getAddressTransactions","params":["synor1...", 100],"id":1}
|
||||
// Response: {"result": [{"txId": "...", "type": "receive", ...}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Hot/Cold Wallet Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Cold Storage │
|
||||
│ (Offline HSM) │
|
||||
│ 95% of funds │
|
||||
└────────┬────────┘
|
||||
│ Manual
|
||||
│ Transfer
|
||||
┌────────▼────────┐
|
||||
│ Warm Wallet │
|
||||
│ (Limited online) │
|
||||
│ 4% of funds │
|
||||
└────────┬────────┘
|
||||
│ Automated
|
||||
│ Threshold
|
||||
┌────────▼────────┐
|
||||
│ Hot Wallet │
|
||||
│ (Always online) │
|
||||
│ 1% of funds │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### Recommended Security Measures
|
||||
|
||||
1. **Multi-signature wallets** for hot wallet (2-of-3 minimum)
|
||||
2. **Rate limiting** on withdrawals (per-user and global)
|
||||
3. **Withdrawal address whitelisting** with cool-down period
|
||||
4. **Monitoring** for unusual patterns
|
||||
5. **Key rotation** schedule (quarterly for hot wallet keys)
|
||||
6. **Audit logging** of all wallet operations
|
||||
|
||||
### Post-Quantum Security
|
||||
|
||||
Synor's hybrid signature scheme provides:
|
||||
|
||||
- **Current security:** Ed25519 against classical attacks
|
||||
- **Future security:** Dilithium3 against quantum attacks
|
||||
- **Defense in depth:** Both must be compromised to forge signatures
|
||||
|
||||
---
|
||||
|
||||
## Test Environment
|
||||
|
||||
### Testnet Information
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Network Name | Synor Testnet |
|
||||
| Address Prefix | `tsynor1` |
|
||||
| RPC Endpoint | `https://testnet-rpc.synor.cc` |
|
||||
| WebSocket | `wss://testnet-ws.synor.cc` |
|
||||
| Faucet | `https://faucet.synor.cc` |
|
||||
| Explorer | `https://testnet.explorer.synor.cc` |
|
||||
|
||||
### Getting Test Tokens
|
||||
|
||||
```bash
|
||||
# Request testnet tokens via faucet API
|
||||
curl -X POST https://faucet.synor.cc/request \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"address": "tsynor1your_testnet_address..."}'
|
||||
```
|
||||
|
||||
### Running Local Testnet
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://github.com/synor/synor.git
|
||||
cd synor
|
||||
|
||||
# Start local testnet with Docker
|
||||
docker compose -f docker-compose.testnet.yml up -d
|
||||
|
||||
# Access local RPC
|
||||
curl http://localhost:17110 ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
### Integration Support
|
||||
|
||||
- **Email:** integration@synor.cc
|
||||
- **Telegram:** @SynorExchangeSupport
|
||||
- **Documentation:** https://docs.synor.cc/exchange
|
||||
|
||||
### API Status
|
||||
|
||||
- **Status Page:** https://status.synor.cc
|
||||
- **Maintenance Notifications:** Subscribe at status page
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 1.0 | 2026-01 | Initial release |
|
||||
|
||||
---
|
||||
|
||||
*Last updated: January 2026*
|
||||
Loading…
Add table
Reference in a new issue