@sequence0/sdk
v4.1.7
Published
Sequence0 Network SDK — Decentralized threshold signatures for any blockchain
Downloads
1,141
Maintainers
Readme
@sequence0/sdk
Decentralized threshold signatures for any blockchain. Create wallets, sign transactions, and broadcast to 94 chains (64 EVM live, 30 non-EVM Treasury addresses pending Phase 10 derivation) — no private keys to store.
60 seconds to a signature
This block is copy-pasteable. No faucet, no funded EOA, no extra config — you'll see a real signature in your terminal and a recovered address that matches the wallet the network just created for you.
mkdir s0-hello && cd s0-hello
npm init -y
npm install @sequence0/sdk ethers tsx
cat > index.ts <<'EOF'
import { Sequence0 } from '@sequence0/sdk';
import { Wallet, verifyMessage } from 'ethers';
async function main() {
const s0 = new Sequence0({
network: 'testnet', // chain 800800
ownerPrivateKey: Wallet.createRandom().privateKey, // throwaway, never holds funds
});
const wallet = await s0.createWallet({ chain: 'ethereum' }); // ~10-30s
const sig = await wallet.signMessage('hello sequence0');
console.log('address :', wallet.address);
console.log('signature:', sig);
console.log('recovered:', verifyMessage('hello sequence0', sig));
// recovered === wallet.address → proof the threshold signature is a real ECDSA signature
}
main().catch((err) => { console.error(err); process.exit(1); });
EOF
npx tsx index.tsExpected output:
address : 0xAbC1234…dEf5
signature: 0x1a2b3c…(130 hex)…
recovered: 0xAbC1234…dEf5If recovered !== address, file an issue — that's a bug.
What just happened
ownerPrivateKeyis a throwaway secret the SDK uses to sign short EIP-712 challenges so the network can prove you asked to sign. It never holds funds. Generate a fresh one per session, or persist your own — your call.createWalletruns a Distributed Key Generation (DKG) ceremony. ~16 of ~24 independent operators collectively hold the FROST shares of your wallet's private key. No single one of them (including Sequence0) ever sees the assembled key.signMessageasks the network to produce a real ECDSA signature (EIP-191 prefixed) thatethers.verifyMessage— and every other EVM tool on the planet — recognises as a valid signature fromwallet.address.
You can send a real transaction next; the only extra step is funding
wallet.address from a faucet (e.g. Sepolia) so it has gas. See
Send 0.001 ETH on Sepolia.
Install
npm install @sequence0/sdk ethersethers is a hard dependency (the SDK uses it for owner proofs + address
derivation). All other chain SDKs (@solana/web3.js, @cosmjs/*, xrpl,
…) are optional peer dependencies — install only the ones for chains
you actually send on.
Mainnet vs testnet. The mainnet operator network is still ramping up; until the on-chain
AgentRegistryhas 16+ active operators (track athttps://explorer.sequence0.network),createWallet({ network: 'mainnet' })throwsDkgError: Not enough agents. Build against testnet first (chain ID800800, RPChttps://rpc.sequence0.network, faucethttps://faucet.sequence0.network).
Send 0.001 ETH on Sepolia in 10 lines
import { Sequence0 } from '@sequence0/sdk';
import { Wallet } from 'ethers';
const s0 = new Sequence0({ network: 'testnet', ownerPrivateKey: Wallet.createRandom().privateKey });
const wallet = await s0.createWallet({ chain: 'ethereum' });
console.log('Fund this address from https://www.alchemy.com/faucets/ethereum-sepolia:', wallet.address);
// ↳ wait for the faucet drop, then:
const txHash = await wallet.sendTransaction({ to: '0xDead...', value: '1000000000000000' }); // 0.001 ETH in wei
console.log('https://sepolia.etherscan.io/tx/' + txHash);Same shape on every chain — only the chain string changes:
await s0.createWallet({ chain: 'bitcoin' }); // → bc1p…
await s0.createWallet({ chain: 'solana' }); // → ed25519 base58
await s0.createWallet({ chain: 'polygon' }); // → 0x… (same wallet works on every EVM chain)Full runnable end-to-end script (with retry/error handling): examples/quickstart-testnet.ts.
Quick Start
import { Sequence0 } from '@sequence0/sdk';
// 1. Initialize the SDK.
// `ownerPrivateKey` is any 32-byte hex secret — the SDK uses it to sign
// EIP-712 auth challenges so agents can verify YOU are asking to sign.
// The key never holds funds; treat it as a session credential.
const s0 = new Sequence0({
network: 'testnet',
ownerPrivateKey: process.env.OWNER_PRIVATE_KEY!, // 0x… (or generate with ethers)
});
// 2. Create a threshold wallet (DKG ceremony, 16-of-24, ~10-30s on testnet).
const wallet = await s0.createWallet({ chain: 'ethereum' });
console.log('Address:', wallet.address); // 0x… EVM address (derived from the FROST pubkey)
console.log('Threshold:', wallet.threshold); // { t: 16, n: 24 }
console.log('PublicKey:', wallet.publicKey); // compressed secp256k1 pubkey
// 3. Fund the wallet from a faucet, then sign + send.
// (testnet wallets need ETH on Sepolia or the Sequence0 testnet to actually broadcast)
const txHash = await wallet.sendTransaction({
to: '0x000000000000000000000000000000000000dEaD',
value: '1000000000000000', // 0.001 ETH in wei
});
console.log('TX Hash:', txHash);
wallet.walletIdvswallet.address. ThewalletIdis the Sequence0-internal identifier you pass back togetWallet(),sign(),requestSignature(). Theaddressis the chain-native account (0x…for EVM,bc1p…for Bitcoin, etc.) derived from the threshold public key.
What's New in v4.1
Bitcoin Taproot (P2TR) Support
Full Bitcoin Taproot transaction lifecycle: address derivation, UTXO management, transaction building, FROST Schnorr signing, and broadcast. FROST-secp256k1 produces BIP-340 compatible Schnorr signatures that are native to Taproot key-path spends.
import { BitcoinTaprootAdapter } from '@sequence0/sdk';
const btc = new BitcoinTaprootAdapter({ network: 'mainnet' });
// Derive a Taproot address from a FROST group public key
const addr = btc.deriveAddress('02abcdef...');
console.log(addr.address); // bc1p...
// Get balance and UTXOs
const balance = await btc.getBalance('bc1p...');
const utxos = await btc.getUTXOs('bc1p...');
// Build a transaction
const unsignedTx = await btc.buildTransaction(
{ to: 'bc1p...recipient', amount: 50000, feeRate: 15 },
'bc1p...sender'
);
// Or use via the Wallet class for automatic signing
const wallet = await s0.createWallet({ chain: 'bitcoin' });
const txHash = await wallet.sendTransaction({
to: 'bc1p...recipient',
amount: 50000,
feeRate: 15,
});ERC-4337 Account Abstraction
Smart accounts backed by FROST threshold signing. Enables gas-sponsored transactions, batch calls, and programmable transaction validation.
import { Sequence0Account } from '@sequence0/sdk';
// Create a new AA wallet backed by FROST
const account = await Sequence0Account.create({
threshold: 16,
committeeSize: 24,
chain: 'ethereum',
ownerPrivateKey: '0x...',
bundlerUrl: 'https://api.pimlico.io/v2/1/rpc?apikey=YOUR_KEY',
});
console.log('Smart Account:', account.getAddress());
// Send a single transaction
const txHash = await account.sendTransaction({
to: '0xRecipient',
value: BigInt('1000000000000000000'),
});
// Batch multiple calls
const txHash2 = await account.sendBatchTransaction([
{ to: '0xTokenA', data: '0xa9059cbb...' },
{ to: '0xTokenB', data: '0xa9059cbb...' },
]);
// Sign messages
const sig = await account.signMessage('Hello from Sequence0 AA!');Features
| Feature | Description |
|---------|-------------|
| Multi-Chain | 94 chains registered in FeeConfig (64 EVM live, 30 non-EVM addresses pending Phase 10 derivation). 28 first-class adapters in src/chains/ with native broadcast helpers; the remaining 66 chains use EVM-family or family-level dispatch. |
| Threshold Signing | FROST (t-of-n) — no single point of failure |
| No Private Keys | Keys are sharded across the agent network |
| Bitcoin Taproot | Native P2TR support with BIP-340 Schnorr signatures |
| Account Abstraction | ERC-4337 smart accounts with batched transactions |
| ERC-20 Tokens | Build and sign ERC-20 transfers, approvals, and balance queries |
| Real-Time Events | WebSocket subscriptions for signing progress |
| Chain Adapters | Auto-builds chain-native transactions |
Supported Chains
EVM (secp256k1)
Ethereum, Polygon, Arbitrum, Optimism, Base, BSC, Avalanche, and 40+ more
Bitcoin (Taproot/Schnorr)
Full P2TR lifecycle: address derivation, UTXO selection, transaction building, Schnorr signing, and broadcast via the BitcoinTaprootAdapter.
Solana (Ed25519)
Native SOL transfers with versioned transactions.
Note: Dogecoin and Litecoin support wallet creation and raw message signing via
sign(). FullsendTransaction()support for these UTXO chains is coming soon.
One Example Per Chain Family
Same SDK, same Sequence0 client, same wallet.sendTransaction() shape — only the chain string changes:
| Family | Curve | Example |
|---|---|---|
| EVM (64 chains live) | secp256k1 | s0.createWallet({ chain: 'ethereum' }) then wallet.sendTransaction({ to, value }) |
| Bitcoin Taproot | secp256k1 (Schnorr) | s0.createWallet({ chain: 'bitcoin' }) then wallet.sendTransaction({ to: 'bc1p…', amount, feeRate }) |
| Solana | ed25519 | s0.createWallet({ chain: 'solana' }) then wallet.sendTransaction({ to, amount }) (lamports) |
| Cosmos / Osmosis | secp256k1 | s0.createWallet({ chain: 'cosmos' }) then build via CosmosAdapter |
| Tron | secp256k1 | s0.createWallet({ chain: 'tron' }) — TronAdapter handles tx envelope |
| Ripple (XRPL) | secp256k1 | s0.createWallet({ chain: 'ripple' }) — RippleAdapter |
| Near / Sui / Aptos / Stellar / Algorand / TON / Tezos | ed25519 | s0.createWallet({ chain: 'near' \| 'sui' \| ... }) |
| Cardano / Polkadot / Kusama | ed25519 | s0.createWallet({ chain: 'cardano' \| 'polkadot' }) |
| Dogecoin / Litecoin / BCH / BSV | secp256k1 | wallet + sign() today; full sendTransaction() coming |
| Hedera / ICP / Stacks / Flow / Casper / Radix / IOTA / Kadena / MultiversX / Kaspa / Nervos | mixed | one adapter per chain — see src/chains/ |
Full chain list lives in the Chain union in src/core/types.ts. Auto-complete in your editor is the canonical source.
API Reference
Sequence0 -- Main Client
const s0 = new Sequence0({
network: 'mainnet', // 'mainnet' | 'testnet'
agentUrl: '...', // Agent node URL (optional)
timeout: 30000, // Request timeout (optional)
});Ownership Verification
Every /sign request requires an ownership proof. Configure an ownerSigner or ownerPrivateKey when creating the SDK instance:
// Option 1: Private key (SDK derives signer automatically)
const s0 = new Sequence0({
network: 'mainnet',
ownerPrivateKey: '0xYourPrivateKey...',
});
// Option 2: Custom signer function
const s0 = new Sequence0({
network: 'mainnet',
ownerSigner: async (digest: Uint8Array) => {
// Sign the 32-byte digest and return 65-byte hex signature
return myWallet.signDigest(digest);
},
});When creating a wallet, pass the creator address to record ownership on-chain:
const wallet = await s0.createWallet({
chain: 'ethereum',
creator: '0xYourAddress...',
});Methods
| Method | Returns | Description |
|--------|---------|-------------|
| createWallet(options) | Promise<Wallet> | Create a new threshold wallet via DKG |
| getWallet(walletId) | Promise<Wallet> | Get an existing wallet |
| listWallets() | Promise<WalletDetail[]> | List all wallets |
| requestSignature(walletId, message) | Promise<string> | Submit a signing request (returns requestId) |
| signAndWait(walletId, message, timeout?) | Promise<string> | Sign and wait for result |
| getStatus() | Promise<StatusResponse> | Get network status |
| health() | Promise<HealthResponse> | Health check |
| subscribe(walletId?) | Promise<WsClient> | Subscribe to real-time events |
| refreshKeys(walletId) | Promise<void> | Proactive key rotation |
Wallet -- Threshold Wallet
const wallet = await s0.createWallet({
chain: 'ethereum',
threshold: { t: 16, n: 24 }, // optional, default shown
curve: 'secp256k1', // auto-detected from chain
});Methods
| Method | Returns | Description |
|--------|---------|-------------|
| sign(transaction) | Promise<SignedTransaction> | Sign a transaction |
| sendTransaction(transaction) | Promise<string> | Sign + broadcast (returns tx hash) |
| broadcast(signedTx) | Promise<string> | Broadcast a signed transaction |
| signMessage(message) | Promise<string> | Sign a message (EIP-191 for EVM) |
| signTypedData(typedData) | Promise<string> | Sign EIP-712 typed data |
| getBalance() | Promise<string> | Get native token balance |
| info() | Record<string, unknown> | Get wallet summary |
BitcoinTaprootAdapter -- Bitcoin P2TR
import { BitcoinTaprootAdapter } from '@sequence0/sdk';
const btc = new BitcoinTaprootAdapter({ network: 'mainnet' });| Method | Returns | Description |
|--------|---------|-------------|
| deriveAddress(pubkeyHex) | TaprootAddressInfo | Derive bc1p... address from FROST public key |
| getBalance(address) | Promise<string> | Get balance in satoshis |
| getUTXOs(address) | Promise<TaprootUtxo[]> | Fetch unspent outputs |
| getFeeRates() | Promise<FeeRateEstimate> | Get recommended fee rates |
| buildTransaction(tx, from) | Promise<string> | Build unsigned transaction |
| buildUnsignedTx(inputs, outputs, feeRate) | UnsignedTaprootTx | Build with explicit inputs/outputs |
| attachSignature(unsignedTx, sig) | Promise<string> | Attach FROST Schnorr signature |
| broadcast(signedTx) | Promise<string> | Broadcast to Bitcoin network |
| getTransaction(txid) | Promise<any> | Get transaction details |
| getBlockHeight() | Promise<number> | Get current block height |
Sequence0Account -- ERC-4337 Smart Account
import { Sequence0Account } from '@sequence0/sdk';
const account = await Sequence0Account.create({
threshold: 16,
committeeSize: 24,
chain: 'ethereum',
ownerPrivateKey: '0x...',
bundlerUrl: 'https://bundler.example.com',
});| Method | Returns | Description |
|--------|---------|-------------|
| Sequence0Account.create(options) | Promise<Sequence0Account> | Create new AA wallet via DKG |
| Sequence0Account.fromExisting(walletId, pubkey, options) | Promise<Sequence0Account> | Reconnect to existing wallet |
| getAddress() | string | Get smart account address |
| sendTransaction(tx) | Promise<string> | Build, sign, submit UserOperation |
| sendBatchTransaction(txs) | Promise<string> | Batch multiple calls |
| signMessage(message) | Promise<string> | Sign with EIP-191 prefix |
| buildUserOp(callData) | Promise<PackedUserOperation> | Build unsigned UserOp |
| submitUserOp(userOp, bundlerUrl?) | Promise<string> | Submit to bundler |
| estimateUserOpGas(userOp) | Promise<UserOperationGasEstimate> | Estimate gas |
| waitForUserOp(hash, timeout?) | Promise<UserOperationReceipt> | Wait for inclusion |
| getBalance() | Promise<string> | Get native token balance |
| isDeployed() | boolean | Check if deployed on-chain |
Chain Adapters
Use chain adapters directly for advanced control:
import {
EthereumAdapter,
BitcoinTaprootAdapter,
SolanaAdapter,
} from '@sequence0/sdk';
const eth = new EthereumAdapter('ethereum', 'https://eth.llamarpc.com');
const btc = new BitcoinTaprootAdapter({ network: 'mainnet' });
const sol = new SolanaAdapter('mainnet');WebSocket Events
const ws = await s0.subscribe('my-wallet-id');
ws.on('SigningStarted', (e) => console.log('Signing started:', e));
ws.on('SigningComplete', (e) => console.log('Signature:', e.signature));
ws.on('WalletCreated', (e) => console.log('New wallet:', e.public_key));
ws.on('FeeCollected', (e) => console.log('Fee collected:', e.tx_hash));
ws.on('Heartbeat', (e) => console.log('Peers:', e.connected_peers));ERC-20 Token Transfers
Send ERC-20 tokens (USDC, WETH, DAI, etc.) from a threshold wallet. The SDK builds the unsigned transfer or approve calldata, produces the signing hash for FROST, and the wallet handles the rest.
import { Sequence0, buildTokenTransfer, getTokenBalance } from '@sequence0/sdk';
const s0 = new Sequence0({ network: 'mainnet', ownerPrivateKey: '0x...' });
const wallet = await s0.createWallet({ chain: 'ethereum' });
// Check USDC balance
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const balance = await getTokenBalance('https://eth.llamarpc.com', USDC, wallet.address);
console.log(`${balance.balance} ${balance.symbol}`); // "1234.56 USDC"
// Build an unsigned USDC transfer
const { unsignedTx, messageHash } = await buildTokenTransfer(
'https://eth.llamarpc.com',
USDC,
wallet.address,
'0xRecipient...',
'100.0', // human-readable amount
1, // Ethereum mainnet chainId
);
// Sign via the threshold network
const signature = await s0.signAndWait(wallet.walletId, messageHash);Approvals
import { buildTokenApproval, getTokenAllowance } from '@sequence0/sdk';
// Approve a DEX to spend USDC
const { unsignedTx, messageHash } = await buildTokenApproval(
'https://eth.llamarpc.com',
USDC,
wallet.address,
'0xDexRouter...',
'1000.0',
1,
);
const signature = await s0.signAndWait(wallet.walletId, messageHash);
// Check current allowance
const allowance = await getTokenAllowance(
'https://eth.llamarpc.com',
USDC,
wallet.address,
'0xDexRouter...',
);
console.log(`Allowance: ${allowance.allowance} ${allowance.symbol}`);Using with wallet.sendTransaction
For the simplest path, encode the ERC-20 calldata into a standard EVM transaction:
import { ethers } from 'ethers';
const iface = new ethers.Interface(['function transfer(address to, uint256 amount)']);
const data = iface.encodeFunctionData('transfer', [
'0xRecipient...',
ethers.parseUnits('100', 6), // 100 USDC (6 decimals)
]);
const txHash = await wallet.sendTransaction({
to: USDC, // token contract as the "to" address
data, // encoded transfer calldata
value: '0', // no ETH value for token transfers
});Merkle Batch Signing
Batch up to 1024 transactions into a single Merkle tree and sign the root once. Proofs for individual transactions are verified on-chain via the BatchVerifier contract. This provides a 1000x throughput multiplier.
import { buildMerkleTree, verifyMerkleProof, generateBatchId, computeBatchMessage } from '@sequence0/sdk';
// Build a Merkle tree from transaction hashes
const txHashes = ['0xabc...', '0xdef...', '0x123...']; // up to 1024
const { root, proofs, leafCount } = buildMerkleTree(txHashes);
// Verify a single leaf locally before submitting on-chain
const proof = proofs.get(0)!;
const valid = verifyMerkleProof(root, txHashes[0], proof);
console.log('Proof valid:', valid); // true
// Generate a batch ID and compute the signing message
const batchId = generateBatchId(txHashes, Date.now());
const message = computeBatchMessage(batchId, root, leafCount, 800801);
// Sign the batch message with a threshold wallet
const sig = await wallet.signMessage(message);Committee Discovery
When the network is sharded into committees, use CommitteeDiscovery to find the agents assigned to a specific wallet's committee. This enables parallel signing across committees for higher throughput.
import { CommitteeDiscovery } from '@sequence0/sdk';
const committee = new CommitteeDiscovery({
rpcUrl: 'https://rpc.sequence0.network',
// AgentRegistry — testnet redeploy 2026-06-04 (chain 800800).
// Always cross-check with contracts/scripts/deployed-addresses.json.
registryAddress: '0xb9ae182892c4a5977abd99bfba865a9111c30200',
// CommitteeRegistry — testnet (chain 800800).
committeeRegistryAddress: '0x762b31879245158e0147c6a9cafcd1997f6e6293',
});
// Get the committee assigned to a wallet
const committeeId = await committee.getCommitteeForWallet('my-wallet-id');
// Get agents in that committee
const agents = await committee.getCommitteeAgents(committeeId);
console.log(`Committee ${committeeId}: ${agents.length} agents`);
// Select a healthy agent for signing
const agentUrl = await committee.selectSigningAgent(committeeId);Error Handling
import { Sequence0Error, DkgError, SigningError, TimeoutError } from '@sequence0/sdk';
try {
await wallet.sendTransaction({ to: '0x...', value: '100' });
} catch (e) {
if (e instanceof TimeoutError) {
console.log('Signing network busy, try again');
} else if (e instanceof SigningError) {
console.log('Signing failed:', e.message);
}
}Any Language (HTTP)
This SDK wraps an internal HTTP + JSON interface exposed by every agent node. The SDK handles connection and discovery automatically, but you can also integrate from any language -- Python, Go, Rust, Java, etc. -- by calling the agent's HTTP endpoint directly:
# Health check
curl http://AGENT_HOST:8080/health
# Create a wallet (DKG)
curl -X POST http://AGENT_HOST:8080/dkg/initiate \
-H 'Content-Type: application/json' \
-d '{"wallet_id":"my-wallet","participants":["peer1","peer2"],"threshold":2,"curve":"secp256k1"}'
# Sign a message
curl -X POST http://AGENT_HOST:8080/sign \
-H 'Content-Type: application/json' \
-d '{"wallet_id":"my-wallet","message":"48656c6c6f"}'
# Poll for signature
curl http://AGENT_HOST:8080/sign/REQUEST_IDTestnet agents: Auto-discovered from the on-chain AgentRegistry
(https://rpc.sequence0.network, chain ID 800800). The SDK does
this for you — no need to hard-code an agentUrl in app code.
Mainnet: Auto-discover from the on-chain AgentRegistry
(https://mainnet-rpc.sequence0.network, chain ID 800801). You can pin
to a specific operator with agentUrl: 'https://your-operator.example/',
but be aware that the SDK will silently fail over to a discovered agent
if the pinned URL is unreachable.
Full HTTP reference: sequence0.network/docs
Networks
| | Mainnet | Testnet |
|---|---|---|
| Chain ID | 800801 | 800800 |
| RPC | https://mainnet-rpc.sequence0.network | https://rpc.sequence0.network |
| Explorer | https://explorer.sequence0.network | https://testnet.sequence0.network |
Economics
Signing fees are collected on the target chain in its native token (ETH on Ethereum, SOL on Solana, BTC on Bitcoin, etc.). The fee is built into the signed transaction itself. The FeeCollector contract on the Sequence0 chain handles governance (fee rates, split ratios) and accounting.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| DkgError: Not enough agents: need 16, only N online | Mainnet operator network has not crossed the 16-agent threshold yet. Use network: 'testnet', or lower the threshold via createWallet({ chain, threshold: { t: 1, n: 1 } }) against a private dev fleet. |
| DkgError: DKG ceremony timed out after 60000ms | Operators dropped out mid-ceremony, or your createWallet event subscription was lost. Retry. If it persists, raise timeout to 120_000ms. |
| Sequence0Error: ownerPrivateKey must be a 32-byte hex string | Pass either 0x + 64 hex chars or 64 hex chars. Generate with ethers.Wallet.createRandom().privateKey. |
| Sequence0Error: creator must be a valid 0x-prefixed Ethereum address | You called createWallet() without ownerPrivateKey in the SDK config AND without creator in the options. Pass one of them. |
| [Sequence0] Connecting to agent via HTTP (unencrypted) warning | Testnet agents currently expose plain HTTP. Set useHttps: false, requireHttps: false in NetworkConfig to silence the discovery warning, or pin to an HTTPS-terminated proxy via agentUrl. |
| Wallet address looks like 02ab… (66 chars, no 0x) | You hit the legacy code path that returned the raw FROST public key. Upgrade to @sequence0/sdk >= 4.1.1 — the SDK now derives the EVM 0x… address from the public key for you. |
Where to next
- 5-minute quickstart (no faucet, no funded EOA):
examples/quickstart.ts— connect, create wallet, sign, verify locally. Heavily commented; copy this file. - End-to-end TX flow:
examples/quickstart-testnet.ts— same as above plus a real Sepolia broadcast (requires faucet). - HTTP / non-TypeScript clients:
sequence0.network/docs#app-developer-sdk. - Faucet:
https://faucet.sequence0.network(testnet only). - Block explorers:
testnet.sequence0.network,explorer.sequence0.network. - Issues / source:
github.com/sequence0network/sequence0.
License
MIT (c) Sequence0 Network
