Wallet Linking
Why link a wallet
Section titled “Why link a wallet”Linking a Solana wallet to your agent:
- Enables presale discount detection. If the wallet is a verified OSR presale buyer, you receive a permanent 20% discount on all operations.
- Associates on-chain identity with your agent for future features.
Endpoint
Section titled “Endpoint”POST /v1/agents/link-walletRequires authentication via X-API-Key header.
Request
Section titled “Request”curl -X POST https://agents.systemr.ai/v1/agents/link-wallet \ -H "X-API-Key: sr_agent_..." \ -H "Content-Type: application/json" \ -d '{ "solana_wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "signature": "BASE58_ENCODED_SIGNATURE", "message": "Link wallet to agent agt_a1b2c3d4" }'Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
solana_wallet_address | string | Yes | Base58-encoded Solana public key. |
signature | string | Yes | Base58-encoded Ed25519 signature proving wallet ownership. |
message | string | Yes | The signed message. Must contain the agent_id. |
How signature verification works
Section titled “How signature verification works”- You create a message string that includes your
agent_id(e.g.,"Link wallet to agent agt_a1b2c3d4"). - You sign the message using your Solana wallet’s private key (Ed25519).
- You send the wallet address, signature, and message to the endpoint.
- System R reconstructs the Ed25519 public key from the wallet address and verifies the signature against the message.
This proves you own the wallet without revealing the private key.
Signing the message
Section titled “Signing the message”Using Phantom wallet (browser)
Section titled “Using Phantom wallet (browser)”const message = `Link wallet to agent ${agentId}`;const encodedMessage = new TextEncoder().encode(message);const signedMessage = await window.solana.signMessage(encodedMessage, "utf8");const signature = bs58.encode(signedMessage.signature);Using Python (solders)
Section titled “Using Python (solders)”from solders.keypair import Keypairimport base58
keypair = Keypair.from_bytes(your_private_key_bytes)message = f"Link wallet to agent {agent_id}"message_bytes = message.encode("utf-8")signature = keypair.sign_message(message_bytes)signature_b58 = base58.b58encode(bytes(signature)).decode("utf-8")Response
Section titled “Response”{ "agent_id": "agt_a1b2c3d4", "solana_wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "is_presale_buyer": true, "message": "Wallet linked. Presale buyer verified. 20% discount active."}If the wallet is not a presale buyer:
{ "agent_id": "agt_a1b2c3d4", "solana_wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "is_presale_buyer": false, "message": "Wallet linked successfully"}Presale verification
Section titled “Presale verification”After verifying the signature, System R queries the Solana mainnet presale program to check if the wallet address is registered as a presale buyer. This is an on-chain PDA (Program Derived Address) lookup.
If the presale check fails due to an RPC error, the wallet is still linked but is_presale_buyer defaults to false. You can retry by linking again.
Security
Section titled “Security”The wallet address is encrypted at rest using per-agent AES-256 encryption. It is decrypted only when making on-chain queries (e.g., presale buyer check).