/crossover/withdraw

POST ASYNC

Withdraws CloudCoins from a locker, converting them to a cryptocurrency (e.g., BTC).

POST /api/v1/crossover/withdraw
Alias: /withdraw-to-crypto

Description

This endpoint initiates a "crossover" transaction, where CloudCoins stored in a RAIDA locker are converted and sent to an external cryptocurrency address. The operation requires specifying the locker, the target currency, the destination address, and other transaction details.

Asynchronous Operation

This operation is asynchronous. It returns a task ID immediately, and the final result must be retrieved by polling the /tasks/{id} endpoint.


Request Body

ParameterTypeRequiredDescription
locker_codestringYesThe transmit code of the locker containing the CloudCoins.
tickerstringYesThe ticker of the target cryptocurrency. Currently, only "BTC" is supported.
addressstringYesThe destination cryptocurrency address where funds will be sent.
conversion_costnumberYesThe agreed-upon cost for the conversion service.
receipt_idstringYesA unique hex identifier for this transaction.
tagstringNoAn optional memo or message for the transaction.

Response (in completed task `data`)

Once the withdrawal task is complete, its `data` field will contain a confirmation of the transaction.

statusstring
The final status of the withdrawal, e.g., "success".
messagestring
A human-readable confirmation message.
txidstring
The transaction ID on the target cryptocurrency's blockchain.
amount_sentnumber
The actual amount of cryptocurrency that was sent.

Examples

JavaScript: Crossover Withdraw

const apiHost = 'http://localhost:8006';

// Generic function to poll any task
async function pollTask(taskId) {
    const taskResponse = await fetch(`${apiHost}/api/v1/tasks/${taskId}`);
    const taskData = await taskResponse.json();
    const task = taskData.payload;

    console.log(`Task ${taskId} progress: ${task.progress}% - ${task.message}`);

    if (task.status === 'completed') {
        console.log(`Task finished successfully!`, task.data);
        return true; // Stop polling
    } else if (task.status === 'error') {
        console.error(`Task failed:`, task.message);
        return true; // Stop polling
    }
    return false; // Continue polling
}

async function crossoverWithdraw(withdrawDetails) {
    try {
        const response = await fetch(`${apiHost}/api/v1/crossover/withdraw`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(withdrawDetails)
        });
        const taskInfo = await response.json();
        const taskId = taskInfo.payload.id;
        console.log(`Crossover withdraw task created with ID: ${taskId}`);

        const pollInterval = setInterval(async () => {
            const isDone = await pollTask(taskId);
            if (isDone) clearInterval(pollInterval);
        }, 2000); // Check every 2 seconds
    } catch (error) {
        console.error('Failed to start withdraw task:', error);
    }
}

// Example: Withdraw CloudCoins to a Bitcoin address
const details = {
    locker_code: "AAC-WS5I",
    ticker: "BTC",
    address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    conversion_cost: 0.00015,
    receipt_id: "930c58c367f4b8a3201a066b69529768",
    tag: "Payment for invoice #123"
};
crossoverWithdraw(details);

cURL: Crossover Withdraw

# Step 1: Initiate the crossover withdraw task
JSON_PAYLOAD='{"locker_code":"AAC-WS5I","ticker":"BTC","address":"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh","conversion_cost":0.00015,"receipt_id":"930c58c367f4b8a3201a066b69529768","tag":"Payment for invoice #123"}'

TASK_ID=$(curl -s -X POST "http://localhost:8006/api/v1/crossover/withdraw" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" | jq -r '.payload.id')
echo "Crossover withdraw task started with ID: $TASK_ID"

# Step 2: Poll the task endpoint until finished
while true; do
  RESPONSE=$(curl -s "http://localhost:8006/api/v1/tasks/$TASK_ID")
  STATUS=$(echo $RESPONSE | jq -r '.payload.status')
  echo "Polling task.. Status: $STATUS"
  
  if [[ "$STATUS" == "completed" ]] || [[ "$STATUS" == "error" ]]; then
    echo "Final Response:"
    echo $RESPONSE | jq
    break
  fi
  
  sleep 2
done

Go: Crossover Withdraw

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

const apiHost = "http://localhost:8006/api/v1"

// Type for the request
type CrossoverWithdrawRequest struct {
	LockerCode     string  `json:"locker_code"`
	Ticker         string  `json:"ticker"`
	CryptoAddress  string  `json:"address"`
	ConversionCost float64 `json:"conversion_cost"`
	ReceiptID      string  `json:"receipt_id"`
	Tag            string  `json:"tag"`
}

// Type for the task response
type TaskResponse struct {
	Payload struct {
		ID       string      `json:"id"`
		Status   string      `json:"status"`
		Progress int         `json:"progress"`
		Message  string      `json:"message"`
		Data     interface{} `json:"data"`
	} `json:"payload"`
}

// pollTask polls a task until it is complete or fails.
func pollTask(taskId string) {
	for {
		resp, err := http.Get(fmt.Sprintf("%s/tasks/%s", apiHost, taskId))
		if err != nil {
			log.Printf("Error polling task: %v\n", err)
			return
		}

		var taskResp TaskResponse
		json.NewDecoder(resp.Body).Decode(&taskResp)
		resp.Body.Close()

		fmt.Printf("Polling... Status: %s, Progress: %d%%\n", taskResp.Payload.Status, taskResp.Payload.Progress)

		if taskResp.Payload.Status == "completed" {
			fmt.Printf("Task completed successfully. Result: %+v\n", taskResp.Payload.Data)
			return
		} else if taskResp.Payload.Status == "error" {
			fmt.Printf("Task failed: %s\n", taskResp.Payload.Message)
			return
		}
		time.Sleep(2 * time.Second)
	}
}

// crossoverWithdraw initiates a withdraw operation and polls for the result.
func crossoverWithdraw(details CrossoverWithdrawRequest) {
	requestBody, _ := json.Marshal(details)

	resp, err := http.Post(fmt.Sprintf("%s/crossover/withdraw", apiHost), "application/json", bytes.NewBuffer(requestBody))
	if err != nil {
		log.Fatalf("Failed to start withdraw task: %v", err)
	}
	defer resp.Body.Close()

	var taskResp TaskResponse
	json.NewDecoder(resp.Body).Decode(&taskResp)

	fmt.Printf("Crossover withdraw task created with ID: %s\n", taskResp.Payload.ID)
	pollTask(taskResp.Payload.ID)
}

func main() {
	details := CrossoverWithdrawRequest{
		LockerCode:     "AAC-WS5I",
		Ticker:         "BTC",
		CryptoAddress:  "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
		ConversionCost: 0.00015,
		ReceiptID:      "930c58c367f4b8a3201a066b69529768",
		Tag:            "Payment for invoice #123",
	}
	crossoverWithdraw(details)
}