| name | tk9-wallet |
|---|---|
| description | Use this skill when the user wants to interact with TK9 blockchain wallets, send tokens, check balances, sign transactions, or perform smart contract operations on TK9 Chain (Chain ID: 7447). Activate when the user mentions wallet operations, token transfers, balance checks, PIN management, or blockchain interactions on the TK9 network. This wallet works ONLY on TK9 Chain (7447) - do not use with any other blockchain. |
IMPORTANT: This is a REST API wallet system. All operations use
curlcommands with JWT authentication. Do NOT use any CLI tools.
TK9 Wallet is a non-custodial wallet system built on PocketBase + dacc-js with hybrid PIN management. It operates exclusively on the TK9 blockchain network with automatic wallet creation, secure PIN-based authentication, and comprehensive blockchain operations.
Base URL: https://wallet.tk9.dev/api/v2
Authentication: Bearer Token (JWT from PocketBase auth)
Blockchain: TK9 Chain (Chain ID: 7447) ONLY
Default Token: 0x20c0000000000000000000000000000000000000 (TK9 token)
Follow this decision tree for all user requests:
User Request
ββ "Create wallet" / "Register" β Follow ONBOARDING FLOW
ββ "Login" / "Sign in" β Follow LOGIN FLOW (OTP)
ββ "Check balance" β Check TOKEN β If expired β LOGIN FLOW β Check balance
ββ "Send tokens" / "Transfer" β Check TOKEN β Check PIN β Execute transfer
ββ "Change PIN" β Check TOKEN β Execute PIN change
ββ Other β Ask for clarification
State Variables to Maintain:
$TOKEN- JWT token from login (required for all authenticated operations)$OTP_ID- OTP ID from request-otp (temporary, used only during login)$WALLET_ADDRESS- User's wallet address (optional, for display)$USER_ID- User's PocketBase ID (optional, for reference)
Persistent Files:
tk9-auth.txt- Stores JWT token (auto-loaded for transactions)tk9-pin.txt- Stores user's PIN (optional, for convenience)
When: User wants to create a new TK9 wallet for the first time.
Bot: "I'll help you create a TK9 wallet. What's your email address?"
User: "[email protected]"
curl -s -X POST https://wallet.tk9.dev/api/v2/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "AutoGeneratedSecurePass123!",
"passwordConfirm": "AutoGeneratedSecurePass123!"
}'Expected Response:
{
"id": "user123",
"email": "[email protected]",
"wallet": "0xA3570FCDA303F55e0978be450f87F885d80a3758",
"pin": "1234",
"verified": false,
"message": "Registration successful. Please check your email to verify your account."
}Save:
$USER_ID= response.id$WALLET_ADDRESS= response.wallet$TEMP_PIN= response.pin (show to user once, will be deleted after change)$VERIFIED= response.verified (should be false)
Bot: "β
Wallet created successfully!
π§ IMPORTANT: Please check your email and click the verification link.
β οΈ If you don't verify within 24 hours, your account will be automatically deleted.
π Your wallet address: $WALLET_ADDRESS
π Temporary PIN: $TEMP_PIN (you'll change this after verification)
Please let me know once you've verified your email."
User clicks verification link in email, then says: "I verified my email"
Bot: "β
Great! Now let's set up your PIN.
You can set a custom PIN (4-6 digits). This PIN will be required for all token transfers.
β οΈ IMPORTANT: After you set your PIN, it will be removed from our database for security.
You MUST remember your PIN - there is no recovery option.
Would you like to:
1. Set a custom PIN (recommended)
2. Keep the temporary PIN for now (you can change it later)"
Option A: User sets custom PIN
Bot: "Please enter your desired PIN (4-6 digits):"
User: "5678"
- First login with temporary PIN (via OTP):
# Request OTP
curl -s -X POST https://wallet.tk9.dev/api/v2/request-otp \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'
# User provides OTP code, then authenticate
TOKEN=$(curl -s -X POST https://wallet.tk9.dev/api/v2/auth-with-otp \
-H "Content-Type: application/json" \
-d '{"otpId": "OTP_ID_HERE", "password": "OTP_CODE_HERE"}' \
| jq -r '.token')- Change PIN:
curl -s -X POST https://wallet.tk9.dev/api/v2/change-pin \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"oldPasswordSecretkey": "1234",
"newPasswordSecretkey": "5678"
}'- Save PIN to file:
echo "5678" > tk9-pin.txt- Confirm to user:
Bot: "β
PIN changed successfully!
π Your PIN has been saved to: tk9-pin.txt
π I've stored your PIN locally for convenience.
β οΈ IMPORTANT SECURITY NOTES:
1. You can delete tk9-pin.txt anytime: rm tk9-pin.txt
2. Every token transfer requires your PIN
3. If you delete the file, you'll need to provide PIN manually each time
4. If you lose your PIN, there is NO recovery - create a new wallet
Your wallet is now ready to use! π"
Option B: User keeps temporary PIN
Bot: "OK, you can continue using the temporary PIN for now.
β οΈ Note: You can change your PIN anytime using the 'change PIN' command.
Your wallet is ready to use! π"
When: User wants to login to access their wallet.
Bot: "Please provide your email to login:"
User: "[email protected]"
curl -s -X POST https://wallet.tk9.dev/api/v2/request-otp \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'Expected Response:
{
"success": true,
"otpId": "abc123xyz",
"message": "OTP sent to your email. Please check your inbox."
}Save: $OTP_ID = response.otpId
Bot: "β
OTP sent to your email!
π§ Please check your inbox for the 8-digit OTP code.
π The code will expire in a few minutes.
Please enter the OTP code:"
User: "12345678"
TOKEN=$(curl -s -X POST https://wallet.tk9.dev/api/v2/auth-with-otp \
-H "Content-Type: application/json" \
-d '{
"otpId": "abc123xyz",
"password": "12345678"
}' | jq -r '.token')
# Save token to file for future use
echo "$TOKEN" > tk9-auth.txt
echo "β
Token saved to tk9-auth.txt"Expected Response:
{
"token": "eyJhbGci...",
"record": {
"id": "user123",
"email": "[email protected]",
"wallet": "0xA3570FCDA303F55e0978be450f87F885d80a3758",
"verified": true
}
}Save: $TOKEN = response.token
Bot: "β
Login successful!
π Wallet: $WALLET_ADDRESS
π° Ready to use your TK9 wallet.
π Auth token saved to: tk9-auth.txt
What would you like to do?
1. Check balance
2. Send tokens
3. Change PIN"
TOKEN=$(curl -s -X POST https://wallet.tk9.dev/api/v2/auth-with-password \
-H "Content-Type: application/json" \
-d '{"identity":"[email protected]","password":"SecurePassword123!"}' \
| jq -r '.token')When: User asks to check their balance.
- Must have valid
$TOKENintk9-auth.txt - If file doesn't exist or token expired β go to LOGIN FLOW
if [ -f tk9-auth.txt ]; then
TOKEN=$(cat tk9-auth.txt)
echo "β
Token loaded from tk9-auth.txt"
else
echo "β οΈ No auth token found. Please login first."
# Go to LOGIN FLOW
ficurl -s https://wallet.tk9.dev/api/v2/balance-token \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chainid": 7447,
"tokenAddress": "0x20c0000000000000000000000000000000000000"
}' | jq '.data.balanceInTokens'curl -s https://wallet.tk9.dev/api/v2/balance-native \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chainid": 7447}' | jq '.data.balanceInTokens'Response to User:
Bot: "π° Your TK9 Token Balance: X.XX TK9
π Your Native Balance: Y.YY TK9"
When: User wants to send/transfer tokens.
- Must have valid
$TOKENintk9-auth.txt(if expired β go to LOGIN FLOW) - Must have PIN (check
tk9-pin.txtor ask user)
if [ -f tk9-auth.txt ]; then
TOKEN=$(cat tk9-auth.txt)
echo "β
Token loaded from tk9-auth.txt"
else
echo "β οΈ No auth token found. Please login first."
# Go to LOGIN FLOW
exit 1
fiif [ -f tk9-pin.txt ]; then
PIN=$(cat tk9-pin.txt)
echo "β
Using PIN from tk9-pin.txt"
else
echo "β οΈ No PIN file found"
fiIf no PIN file, ask user:
Bot: "To transfer tokens, I need your PIN.
Options:
1. Enter your PIN now (I won't save it)
2. Save your PIN to tk9-pin.txt for future use:
echo \"YOUR_PIN\" > tk9-pin.txt
Please provide your PIN:"
Bot: "Please provide:
1. Recipient wallet address (0x...)"
User: "0xA3570FCDA303F55e0978be450f87F885d80a3758"
Bot: "2. Amount to send:"
User: "0.1"
Bot: "3. Token (default is TK9 token, or specify another token address):"
User: "default" or "0x..."
BALANCE=$(curl -s https://wallet.tk9.dev/api/v2/balance-token \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chainid": 7447,
"tokenAddress": "0x20c0000000000000000000000000000000000000"
}' | jq -r '.data.balanceInTokens')
echo "Current balance: $BALANCE"If insufficient balance:
Bot: "β οΈ Insufficient balance.
Your balance: X.XX TK9
Amount to send: Y.YY TK9
Please add more funds to your wallet first."
curl -s -X POST https://wallet.tk9.dev/api/v2/send-token \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"chainid": 7447,
"tokenAddress": "0x20c0000000000000000000000000000000000000",
"to": "0xA3570FCDA303F55e0978be450f87F885d80a3758",
"amount": "0.1",
"passwordSecretkey": "5678"
}'Success Response:
{
"success": true,
"data": {
"transactionHash": "0x123abc...",
"from": "0x...",
"to": "0xA3570FCDA303F55e0978be450f87F885d80a3758",
"amount": "0.1",
"tokenAddress": "0x20c00..."
}
}Confirm to User:
Bot: "β
Transfer successful!
π€ Amount: 0.1 TK9
π To: 0xA3570FCDA303F55e0978be450f87F885d80a3758
π Transaction: 0x123abc...
View on explorer: https://chain.tk9.dev/tx/0x123abc..."
When: User wants to change their PIN.
- Must have valid
$TOKENintk9-auth.txt(if expired β go to LOGIN FLOW) - Must know current PIN
if [ -f tk9-auth.txt ]; then
TOKEN=$(cat tk9-auth.txt)
echo "β
Token loaded from tk9-auth.txt"
else
echo "β οΈ No auth token found. Please login first."
# Go to LOGIN FLOW
exit 1
fiBot: "Please enter your current PIN:"
User: "1234"
Bot: "Please enter your new PIN (4-6 digits):"
User: "5678"
curl -s -X POST https://wallet.tk9.dev/api/v2/change-pin \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"oldPasswordSecretkey": "1234",
"newPasswordSecretkey": "5678"
}'echo "5678" > tk9-pin.txtBot: "β
PIN changed successfully!
π Your PIN has been updated in tk9-pin.txt
β οΈ IMPORTANT:
- All future transfers will use your new PIN
- Your old PIN no longer works
- Keep your new PIN secure"
1. Chain ID Rule:
- ALWAYS use
chainid: 7447(TK9 Chain) - Never ask user for chain ID
- Never use any other chain ID
- All operations are on TK9 Chain only
2. First Time (Custodial Mode):
- PIN is auto-generated and stored in database
- API calls work WITHOUT explicit
passwordSecretkeyparameter - System retrieves PIN from database automatically
- BUT: Strongly recommend user to change PIN immediately
3. After PIN Change (Non-Custodial Mode):
- PIN is REMOVED from database permanently
- ALL transfers REQUIRE
passwordSecretkeyparameter - Server has zero knowledge of user's PIN
- User must provide PIN every time OR save to
tk9-pin.txt
4. PIN Storage:
- AI agent CAN save PIN to
tk9-pin.txtin workspace - User can delete the file anytime:
rm tk9-pin.txt - File is local only - not uploaded to server
- User can recreate file:
echo "PIN" > tk9-pin.txt
5. PIN Format:
- 4-6 digits only
- Examples:
1234,567890 - No letters or special characters
{
"success": true,
"data": {
"transactionHash": "0x...",
"from": "0x...",
"to": "0x...",
"amount": 0.1
}
}Action: Return transaction hash and details to user with explorer link.
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient token balance"
}
}Action: Report error clearly with suggested action.
Fix: Re-login with OTP
# Request new OTP
curl -s -X POST https://wallet.tk9.dev/api/v2/request-otp \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'
# User provides OTP code, then authenticate
TOKEN=$(curl -s -X POST https://wallet.tk9.dev/api/v2/auth-with-otp \
-H "Content-Type: application/json" \
-d '{"otpId": "NEW_OTP_ID", "password": "OTP_CODE"}' \
| jq -r '.token')
# Save new token
echo "$TOKEN" > tk9-auth.txt
echo "β
New token saved to tk9-auth.txt"Fix: Ask user for PIN or create file
Bot: "No PIN file found. Please:
1. Enter your PIN now, or
2. Create tk9-pin.txt: echo \"YOUR_PIN\" > tk9-pin.txt"
Fix: User must provide correct PIN
- No PIN reset available (non-custodial)
- If forgotten, user must create new account
Fix: Check balance and inform user
- Show current balance
- Show required amount
- Ask user to fund wallet first
Fix: Verify address format
- Must start with
0x - Must be 42 characters (0x + 40 hex chars)
- Example:
0xA3570FCDA303F55e0978be450f87F885d80a3758
This wallet system operates exclusively on TK9 Chain:
| Property | Value |
|---|---|
| Chain ID | 7447 |
| Network Name | TK9 Chain |
| Native Token | TK9 |
| Block Explorer | https://chain.tk9.dev |
| RPC URL | https://rpc.tk9.dev |
- ALWAYS use
chainid: 7447in ALL API calls - NEVER ask user which chain to use
- NEVER use any other chain ID (7442, 1, 56, etc.)
- All wallet operations are on TK9 Chain only
- If user mentions other chains, inform them this wallet is TK9-only
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/v2/register |
POST | No | Register new user |
/api/v2/request-otp |
POST | No | Request OTP for login |
/api/v2/auth-with-otp |
POST | No | Login with OTP |
/api/v2/auth-with-password |
POST | No | Login with password (fallback) |
/api/v2/change-pin |
POST | Yes | Change user PIN |
/api/v2/balance-native |
GET | Yes | Check native balance |
/api/v2/balance-token |
GET | Yes | Check token balance |
/api/v2/send-native |
POST | Yes | Send native tokens |
/api/v2/send-token |
POST | Yes | Send ERC-20 tokens |
/api/v2/write-contract |
POST | Yes | Call smart contract |
/api/v2/sign-typed-data |
POST | Yes | Sign EIP-712 data |
| Operation | Auth Token | Chain ID | PIN Required |
|---|---|---|---|
| Register | No | N/A | No |
| Login (OTP) | No | N/A | No |
| Login (Password) | No | N/A | No |
| Check Balance | Yes | 7447 | No |
| Send Tokens | Yes | 7447 | Yes (after PIN change) |
| Send Native | Yes | 7447 | Yes (after PIN change) |
| Change PIN | Yes | N/A | Yes (old PIN) |
| Write Contract | Yes | 7447 | Yes |
| Sign Data | Yes | 7447 | Yes |
chainid: 7447. Never use any other value.
- Never expose user's PIN in logs or responses
- Always use HTTPS for production
- JWT tokens expire after 7 days - re-authenticate when needed
- Token is stored in
tk9-auth.txt - Delete file if user logs out:
rm tk9-auth.txt
- Token is stored in
- PIN is non-recoverable after first change
- Store PIN securely - tk9-pin.txt is local only
- Verify email before operations - unverified accounts deleted after 24h
- Auth token file -
tk9-auth.txtcontains sensitive JWT token- Do not commit to git
- Delete when user logs out
- Re-login if token expires
Last Updated: 2026-04-05
Version: 1.1.0
Compatible with: Clawbot, any curl-capable AI agent