Skip to main content
This guide walks you through creating a wallet, signing a message, and sending your first transaction using the MoonKey REST API.

Prerequisites

Before you begin, make sure you have:
  • Completed the REST API setup guide
  • Your MoonKey API key (test or live)
  • A test user ID (or follow step 0 to create one)
All examples in this guide use test API keys. Replace sk_test_your_api_key_here with your actual API key.

Create a User (Optional)

If you want your wallet to be owned by a specific user, first create a user account:
curl -X POST "https://api.moonkey.fun/v1/auth/users/create" \
  -H "Authorization: Bearer sk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'
The response will include the user ID:
{
  "id": "user_2Cu2uVhYy0OVgRcO913OsqIVaPI",
  "app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
  "email": "user@example.com",
  "created_at": 1659638371,
  "updated_at": 1659638371
}
Save the id field from the response. You’ll need it in the next step to create a wallet for this user.

1. Create a Wallet

Let’s create an Ethereum wallet for your user:
curl -X POST "https://api.moonkey.fun/v1/wallets/create" \
  -H "Authorization: Bearer sk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_type": "ethereum",
    "user_id": "user_2Cu2uVhYy0OVgRcO913OsqIVaPI"
  }'
The response will include the wallet ID and public address:
{
  "id": "wallet_2Cu2uYcbwY9kcAFe2zd0P0SHftK",
  "app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
  "user_id": "user_2Cu2uVhYy0OVgRcO913OsqIVaPI",
  "public_address": "0xf1347fd847f19c250b4c9678ecaa27b0f6ce8804",
  "wallet_type": "ethereum",
  "verified": true,
  "is_default": true,
  "is_read_only": false,
  "is_imported": false,
  "created_at": 1659638371,
  "updated_at": 1659638371
}
If a wallet of the same type already exists for the user, MoonKey will return the existing wallet instead of creating a new one.
Save the wallet id and public_address. You’ll need these for the next steps.

2. Sign a Message

Now let’s sign a message with your newly created wallet:
curl -X POST "https://api.moonkey.fun/v1/wallets/wallet_2Cu2uYcbwY9kcAFe2zd0P0SHftK/sign_message" \
  -H "Authorization: Bearer sk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Hello from MoonKey!"
  }'
The response will contain the signed message:
{
  "wallet_id": "wallet_2Cu2uYcbwY9kcAFe2zd0P0SHftK",
  "wallet": {
    "id": "wallet_2Cu2uYcbwY9kcAFe2zd0P0SHftK",
    "app_id": "app_25ldv51seNohTaYRsxdfoxMlAa2",
    "user_id": "user_26l6ha8syVN8oqmaHaFShTxZ5RC",
    "public_address": "0xb6acedc0cdcab7a4bb6c236976bb7df63bbcd567",
    "wallet_type": "ethereum",
    "verified": true,
    "is_default": true,
    "is_read_only": false,
    "is_imported": false,
    "created_at": 1647985945,
    "updated_at": 1647985945
  },
  "signature": "0xc8723cfad978035ad3b960beade5237477aa91a9b01ba238d859e2a6e0fbded322e4732d3252afc4f7bec0018cc7bdddfe90547cc4fa985a400744315316198e01"
}

3. Send a Transaction

Finally, let’s send a transaction on Ethereum’s testnet, Sepolia:
curl -X POST "https://api.moonkey.fun/v1/wallets/wallet_2Cu2uYcbwY9kcAFe2zd0P0SHftK/sign_transaction" \
  -H "Authorization: Bearer sk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "eth_transaction": {
      "to": "0xE9534C9fAF3cDBc636c25E1981A80EfaE03f187a",
      "value": "0x38d7ea4c68000",
      "nonce": "0x8",
      "maxPriorityFeePerGas": "0x77359400",
      "maxFeePerGas": "0xdf8475800",
      "gas": "0x5208",
      "chainId": "0xaa36a7"
    }
  }'
You’ll need to fund your wallet with Sepolia ETH for this step. Use a Sepolia faucet to send test ETH to your wallet’s public_address.
The response will contain the signature and signed transaction:
{
  "wallet_id": "wallet_26l6hdwAXQr0y573AhQTXNDkyqK",
  "wallet": {
    "id": "wallet_26l6hdwAXQr0y573AhQTXNDkyqK",
    "app_id": "app_25ldv51seNohTaYRsxdfoxMlAa2",
    "user_id": "user_26l6ha8syVN8oqmaHaFShTxZ5RC",
    "public_address": "0xb6acedc0cdcab7a4bb6c236976bb7df63bbcd567",
    "wallet_type": "ethereum",
    "verified": true,
    "is_default": true,
    "is_read_only": false,
    "is_imported": false,
    "created_at": 1647985945,
    "updated_at": 1647985945
  },
  "signature": "0x744b61c44cdb250b89438709a9438a0b9e30c9c46e29776c93fb5e150e56021a",
  "signed_transaction": "0xb87502f87205088477359400850df847580082520894e9534c9faf3cdbc636c25e1981a80efae03f187a87038d7ea4c6800080c001a0cd31b38c3e3a48230bee2d5c687a0b2a5efcb298c58cfc3b43449eefd17857cfa03f95b8bcad72f7bdca59025e797781f4ba3fde826f62b9d6997aaf19a7d7591b"
}

Broadcasting the Transaction

The signed_transaction is ready to be broadcast to the Ethereum network. You can use it with the eth_sendRawTransaction RPC method:
const signedTx = result.signed_transaction;

// Using a public RPC endpoint
const rpcResponse = await fetch('https://rpc.sepolia.org', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'eth_sendRawTransaction',
    params: [signedTx],
    id: 1
  })
});

const txResult = await rpcResponse.json();
console.log('Transaction hash:', txResult.result);
View your transaction on Sepolia Etherscan by searching for the transaction hash.

Understanding Transaction Parameters

When sending a transaction, you need to provide several parameters:
ParameterDescriptionExample
toRecipient address0xE9534C9fAF3cDBc636c25E1981A80EfaE03f187a
valueAmount in wei (hex)0x38d7ea4c68000 (0.001 ETH)
nonceTransaction count for the address0x8
maxPriorityFeePerGasPriority fee (hex)0x77359400
maxFeePerGasMax total fee (hex)0xdf8475800
gasGas limit (hex)0x5208 (21000 for simple transfer)
chainIdNetwork chain ID (hex)0xaa36a7 (Sepolia)
Use tools like eth-converter.com to convert between decimal and hex values for ETH amounts and gas prices.

Creating Solana Wallets

MoonKey also supports Solana wallets. To create a Solana wallet, simply change the wallet_type:
curl -X POST "https://api.moonkey.fun/v1/wallets/create" \
  -H "Authorization: Bearer sk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_type": "solana",
    "user_id": "user_2Cu2uVhYy0OVgRcO913OsqIVaPI"
  }'

Best Practices

Security

  • Never expose API keys - Keep your secret API keys secure on your backend
  • Use test keys for development - Test thoroughly before switching to live keys
  • Validate user actions - Always verify that requests come from authenticated users

Transaction Safety

  • Verify addresses - Always double-check recipient addresses before sending transactions
  • Test on testnet first - Use Sepolia for Ethereum or Devnet for Solana before going to mainnet
  • Monitor transaction status - Track transactions and handle failures gracefully
  • Use appropriate gas limits - Ensure transactions have enough gas to complete

Error Handling

Always implement proper error handling for API requests:
try {
  const response = await fetch('https://api.moonkey.fun/v1/wallets/create', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      wallet_type: 'ethereum',
      user_id: userId
    })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Failed to create wallet');
  }

  const wallet = await response.json();
  return wallet;
} catch (error) {
  console.error('Wallet creation failed:', error.message);
  // Handle error appropriately for your application
}

Troubleshooting

Common Issues

401 Unauthorized
  • Verify your API key is correct
  • Ensure you’re using the Bearer token format
  • Check that your API key hasn’t been revoked
404 Not Found
  • Verify the wallet ID is correct
  • Ensure the wallet belongs to your app
  • Check that the user ID exists
Transaction Fails
  • Verify the wallet has sufficient balance
  • Check that gas limits and fees are appropriate
  • Ensure the recipient address is valid
  • Verify you’re on the correct network (testnet vs mainnet)
Rate Limiting
  • Implement exponential backoff for retries
  • Cache wallet data when possible
  • Batch operations where appropriate

Support

Need help?